From 853a008431356995aeb237cfd55cc43f42695a7b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:13:37 +0100 Subject: [PATCH] Tasmota changes * IPv6 support * remove WPA2 Enterprise * rm `WiFiClientSecure` * "--dont-append-digest" * rm not needed librarys * safeboot in Tasmota project * Revert "WiFiSTA - allow using DHCP again after disconnecting static IP (#8848)" (#297) * remove zigbee libs --- CMakeLists.txt | 68 +----- README.md | 67 +----- cores/esp32/Esp.cpp | 4 + cores/esp32/IPAddress.cpp | 225 ++++++++++++++---- cores/esp32/IPAddress.h | 161 +++++++++++-- idf_component.yml | 38 --- libraries/Ethernet/src/ETH.cpp | 3 + libraries/Ethernet/src/ETH.h | 2 +- libraries/HTTPClient/src/HTTPClient.cpp | 96 -------- libraries/HTTPClient/src/HTTPClient.h | 1 - libraries/Update/src/Updater.cpp | 2 + libraries/WiFi/src/WiFiClient.cpp | 69 +++++- libraries/WiFi/src/WiFiGeneric.cpp | 58 ++++- libraries/WiFi/src/WiFiGeneric.h | 7 + libraries/WiFi/src/WiFiMulti.cpp | 7 + libraries/WiFi/src/WiFiMulti.h | 2 + libraries/WiFi/src/WiFiSTA.cpp | 96 +------- libraries/WiFi/src/WiFiSTA.h | 1 + libraries/WiFi/src/WiFiServer.cpp | 28 ++- libraries/WiFi/src/WiFiServer.h | 1 - libraries/WiFi/src/WiFiUdp.cpp | 168 ++++++++++--- libraries/WiFiClientSecure/src/ssl_client.cpp | 2 +- tools/platformio-build.py | 34 +-- 23 files changed, 649 insertions(+), 491 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0834ae1ec34..fc90b12ae39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,15 +76,8 @@ set(CORE_SRCS set(LIBRARY_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp libraries/AsyncUDP/src/AsyncUDP.cpp - libraries/BluetoothSerial/src/BluetoothSerial.cpp - libraries/BluetoothSerial/src/BTAddress.cpp - libraries/BluetoothSerial/src/BTAdvertisedDeviceSet.cpp - libraries/BluetoothSerial/src/BTScanResultsSet.cpp libraries/DNSServer/src/DNSServer.cpp libraries/EEPROM/src/EEPROM.cpp - libraries/ESP_I2S/src/ESP_I2S.cpp - libraries/ESP_SR/src/ESP_SR.cpp - libraries/ESP_SR/src/esp32-hal-sr.c libraries/ESPmDNS/src/ESPmDNS.cpp libraries/Ethernet/src/ETH.cpp libraries/FFat/src/FFat.cpp @@ -93,23 +86,12 @@ set(LIBRARY_SRCS libraries/HTTPClient/src/HTTPClient.cpp libraries/HTTPUpdate/src/HTTPUpdate.cpp libraries/LittleFS/src/LittleFS.cpp - libraries/Insights/src/Insights.cpp libraries/NetBIOS/src/NetBIOS.cpp libraries/Preferences/src/Preferences.cpp - libraries/RainMaker/src/RMaker.cpp - libraries/RainMaker/src/RMakerNode.cpp - libraries/RainMaker/src/RMakerParam.cpp - libraries/RainMaker/src/RMakerDevice.cpp - libraries/RainMaker/src/RMakerType.cpp - libraries/RainMaker/src/RMakerQR.cpp - libraries/RainMaker/src/RMakerUtils.cpp - libraries/RainMaker/src/AppInsights.cpp libraries/SD_MMC/src/SD_MMC.cpp libraries/SD/src/SD.cpp libraries/SD/src/sd_diskio.cpp libraries/SD/src/sd_diskio_crc.c - libraries/SimpleBLE/src/SimpleBLE.cpp - libraries/SPIFFS/src/SPIFFS.cpp libraries/SPI/src/SPI.cpp libraries/Ticker/src/Ticker.cpp libraries/Update/src/Updater.cpp @@ -126,8 +108,6 @@ set(LIBRARY_SRCS libraries/WebServer/src/WebServer.cpp libraries/WebServer/src/Parsing.cpp libraries/WebServer/src/detail/mimetable.cpp - libraries/WiFiClientSecure/src/ssl_client.cpp - libraries/WiFiClientSecure/src/WiFiClientSecure.cpp libraries/WiFi/src/WiFiAP.cpp libraries/WiFi/src/WiFiClient.cpp libraries/WiFi/src/WiFi.cpp @@ -137,54 +117,16 @@ set(LIBRARY_SRCS libraries/WiFi/src/WiFiServer.cpp libraries/WiFi/src/WiFiSTA.cpp libraries/WiFi/src/WiFiUdp.cpp - libraries/WiFiProv/src/WiFiProv.cpp libraries/Wire/src/Wire.cpp ) -set(BLE_SRCS - libraries/BLE/src/BLE2902.cpp - libraries/BLE/src/BLE2904.cpp - libraries/BLE/src/BLEAddress.cpp - libraries/BLE/src/BLEAdvertisedDevice.cpp - libraries/BLE/src/BLEAdvertising.cpp - libraries/BLE/src/BLEBeacon.cpp - libraries/BLE/src/BLECharacteristic.cpp - libraries/BLE/src/BLECharacteristicMap.cpp - libraries/BLE/src/BLEClient.cpp - libraries/BLE/src/BLEDescriptor.cpp - libraries/BLE/src/BLEDescriptorMap.cpp - libraries/BLE/src/BLEDevice.cpp - libraries/BLE/src/BLEEddystoneTLM.cpp - libraries/BLE/src/BLEEddystoneURL.cpp - libraries/BLE/src/BLEExceptions.cpp - libraries/BLE/src/BLEHIDDevice.cpp - libraries/BLE/src/BLERemoteCharacteristic.cpp - libraries/BLE/src/BLERemoteDescriptor.cpp - libraries/BLE/src/BLERemoteService.cpp - libraries/BLE/src/BLEScan.cpp - libraries/BLE/src/BLESecurity.cpp - libraries/BLE/src/BLEServer.cpp - libraries/BLE/src/BLEService.cpp - libraries/BLE/src/BLEServiceMap.cpp - libraries/BLE/src/BLEUtils.cpp - libraries/BLE/src/BLEUUID.cpp - libraries/BLE/src/BLEValue.cpp - libraries/BLE/src/FreeRTOS.cpp - libraries/BLE/src/GeneralUtils.cpp - ) - set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ libraries/ArduinoOTA/src libraries/AsyncUDP/src - libraries/BLE/src - libraries/BluetoothSerial/src libraries/DNSServer/src libraries/EEPROM/src - libraries/ESP_I2S/src - libraries/ESP_SR/src - libraries/ESP32/src libraries/ESPmDNS/src libraries/Ethernet/src libraries/FFat/src @@ -192,29 +134,23 @@ set(includedirs libraries/HTTPClient/src libraries/HTTPUpdate/src libraries/LittleFS/src - libraries/Insights/src libraries/NetBIOS/src libraries/Preferences/src - libraries/RainMaker/src libraries/SD_MMC/src libraries/SD/src - libraries/SimpleBLE/src - libraries/SPIFFS/src libraries/SPI/src libraries/Ticker/src libraries/Update/src libraries/USB/src libraries/WebServer/src - libraries/WiFiClientSecure/src libraries/WiFi/src - libraries/WiFiProv/src libraries/Wire/src ) -set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS}) +set(srcs ${CORE_SRCS} ${LIBRARY_SRCS}) set(priv_includes cores/esp32/libb64) set(requires spi_flash esp_partition mbedtls wifi_provisioning wpa_supplicant esp_adc esp_eth http_parser) -set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid) +set(priv_requires fatfs nvs_flash app_update bootloader_support bt esp_hid) idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires}) diff --git a/README.md b/README.md index 09556346255..bacb40b5ec4 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,6 @@ -# Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 +# Tasmota Platformio Arduino for ESP32, ESP32-S2, ESP32-S3, ESP32-C2, ESP32-C3, ESP32-C6 and ESP32-H2 -![Build Status](https://github.com/espressif/arduino-esp32/workflows/ESP32%20Arduino%20CI/badge.svg) [![Documentation Status](https://readthedocs.com/projects/espressif-arduino-esp32/badge/?version=latest)](https://docs.espressif.com/projects/arduino-esp32/en/latest/?badge=latest) -[![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml?link=http://https://github.com/espressif/arduino-esp32/blob/master/LIBRARIES_TEST.md) - -### Need help or have a question? Join the chat at [Gitter](https://gitter.im/espressif/arduino-esp32) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions) - -## Contents - - - [Development Status](#development-status) - - [Development Planning](#development-planning) - - [Documentation](#documentation) - - [Supported Chips](#supported-chips) - - [Decoding exceptions](#decoding-exceptions) - - [Issue/Bug report template](#issuebug-report-template) - - [Contributing](#contributing) - -### Development Status - -Latest Stable Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) - -Latest Development Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) - -### Development Planning - -Our Development is fully tracked on this public **[Roadmap 🎉](https://github.com/orgs/espressif/projects/3)** - -For even more information you can join our **[Monthly Community Meetings 🔔](https://github.com/espressif/arduino-esp32/discussions/categories/monthly-community-meetings).** +### [![GitHub Releases](https://img.shields.io/github/downloads/tasmota/arduino-esp32/total?label=downloads)](https://github.com/tasmota/arduino-esp32/releases/latest) ### Documentation @@ -37,47 +12,19 @@ You can use the [Arduino-ESP32 Online Documentation](https://docs.espressif.com/ --- -* [Getting Started](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html) -* [Installing (Windows, Linux and macOS)](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html) -* [Libraries](https://docs.espressif.com/projects/arduino-esp32/en/latest/libraries.html) -* [Arduino as an ESP-IDF component](https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html) -* [FAQ](https://docs.espressif.com/projects/arduino-esp32/en/latest/faq.html) -* [Troubleshooting](https://docs.espressif.com/projects/arduino-esp32/en/latest/troubleshooting.html) - ### Supported Chips -Here are the ESP32 series supported by the Arduino-ESP32 project: +Here are the ESP32 series supported by the Tasmota Arduino-ESP32 project: | **SoC** | **Stable** | **Development** | **Datasheet** | |----------|:----------:|:---------------:|:-------------------------------------------------------------------------------------------------:| -| ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) | +| ESP32 | Yes | Yes | [ESP32](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) | +| ESP32solo1| Yes | Yes | [ESP32solo1](https://www.espressif.com/sites/default/files/documentation/esp32-solo-1_datasheet_en.pdf) | | ESP32-S2 | Yes | Yes | [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) | -| ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) | | ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) | +| ESP32-C3 | Yes | Yes | [ESP32-C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) | +| ESP32-C2 | No | Yes | [ESP32-C2](https://www.espressif.com/sites/default/files/documentation/esp8684_datasheet_en.pdf) | | ESP32-C6 | No | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) | | ESP32-H2 | No | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) | For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page. - -### Decoding exceptions - -You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace. - -### Issue/Bug report template - -Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [Type: For reference](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue+label%3A%22Type%3A+For+reference%22+). - -Finally, if you are sure no one else had the issue, follow the **Issue template** or **Feature request template** while reporting any [new Issue](https://github.com/espressif/arduino-esp32/issues/new/choose). - -### External libraries compilation test - -We have set-up CI testing for external libraries for ESP32 Arduino core. You can check test results in the file [LIBRARIES_TEST](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md). -For more information and how to add your library to the test see [external library testing](https://docs.espressif.com/projects/arduino-esp32/en/latest/external_libraries_test.html) in the documentation. - -### Contributing - -We welcome contributions to the Arduino ESP32 project! - -See [contributing](https://docs.espressif.com/projects/arduino-esp32/en/latest/contributing.html) in the documentation for more information on how to contribute to the project. - -> We would like to have this repository in a polite and friendly atmosphere, so please be kind and respectful to others. For more details, look at [Code of Conduct](https://github.com/espressif/arduino-esp32/blob/master/CODE_OF_CONDUCT.md). diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp index 0d812b2fcb0..417fcc29b88 100644 --- a/cores/esp32/Esp.cpp +++ b/cores/esp32/Esp.cpp @@ -248,6 +248,10 @@ String EspClass::getSketchMD5() md5.add(buf.get(), readBytes); lengthLeft -= readBytes; offset += readBytes; + + #if CONFIG_FREERTOS_UNICORE + delay(1); // Fix solo WDT + #endif } md5.calculate(); result = md5.toString(); diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index 0575363f254..1722065c7bd 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -20,68 +20,86 @@ #include #include #include +#include -IPAddress::IPAddress() -{ - _address.dword = 0; +IPAddress::IPAddress() { +#if LWIP_IPV6 + _ip = *IP6_ADDR_ANY; +#else + _ip = *IP_ADDR_ANY; +#endif } -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +IPAddress::IPAddress(const IPAddress& from) { - _address.bytes[0] = first_octet; - _address.bytes[1] = second_octet; - _address.bytes[2] = third_octet; - _address.bytes[3] = fourth_octet; + ip_addr_copy(_ip, from._ip); } -IPAddress::IPAddress(uint32_t address) -{ - _address.dword = address; +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { + uint8_t addr[] { + first_octet, + second_octet, + third_octet, + fourth_octet, + }; + *this = &addr[0]; } -IPAddress::IPAddress(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); +IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16) { + setV6(); + (*this)[0] = o1; + (*this)[1] = o2; + (*this)[2] = o3; + (*this)[3] = o4; + (*this)[4] = o5; + (*this)[5] = o6; + (*this)[6] = o7; + (*this)[7] = o8; + (*this)[8] = o9; + (*this)[9] = o10; + (*this)[10] = o11; + (*this)[11] = o12; + (*this)[12] = o13; + (*this)[13] = o14; + (*this)[14] = o15; + (*this)[15] = o16; } -IPAddress& IPAddress::operator=(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); - return *this; +IPAddress::IPAddress(IPType type, const uint8_t *address) { + IPAddress(type, address, 0); } -IPAddress& IPAddress::operator=(uint32_t address) -{ - _address.dword = address; - return *this; -} +IPAddress::IPAddress(IPType type, const uint8_t *address, uint8_t zone) { + if (type == IPv4) { + setV4(); + memcpy(&this->_ip.u_addr.ip4, address, 4); + } else if (type == IPv6) { + setV6(); + memcpy(&this->_ip.u_addr.ip6.addr[0], address, 16); + setZone(zone); + } else { +#if LWIP_IPV6 + _ip = *IP6_ADDR_ANY; +#else + _ip = *IP_ADDR_ANY; +#endif + } -bool IPAddress::operator==(const uint8_t* addr) const -{ - return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; } -size_t IPAddress::printTo(Print& p) const -{ - size_t n = 0; - for(int i = 0; i < 3; i++) { - n += p.print(_address.bytes[i], DEC); - n += p.print('.'); +bool IPAddress::fromString(const char *address) { + if (!fromString4(address)) { +#if LWIP_IPV6 + return fromString6(address); +#else + return false; +#endif } - n += p.print(_address.bytes[3], DEC); - return n; -} - -String IPAddress::toString() const -{ - char szRet[16]; - sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]); - return String(szRet); + return true; } -bool IPAddress::fromString(const char *address) -{ - // TODO: add support for "a", "a.b", "a.b.c" formats +bool IPAddress::fromString4(const char *address) { + // TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats uint16_t acc = 0; // Accumulator uint8_t dots = 0; @@ -103,7 +121,7 @@ bool IPAddress::fromString(const char *address) // Too much dots (there must be 3 dots) return false; } - _address.bytes[dots++] = acc; + (*this)[dots++] = acc; acc = 0; } else @@ -117,9 +135,122 @@ bool IPAddress::fromString(const char *address) // Too few dots (there must be 3 dots) return false; } - _address.bytes[3] = acc; + (*this)[3] = acc; + + setV4(); return true; } +IPAddress& IPAddress::operator=(const uint8_t *address) { + uint32_t value; + memcpy_P(&value, address, sizeof(value)); + *this = value; + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) { + setV4(); + v4() = address; + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) const { + if (!isV4()) { + return false; + } + + uint32_t value; + memcpy_P(&value, addr, sizeof(value)); + + return v4() == value; +} + +size_t IPAddress::printTo(Print& p) const { + size_t n = 0; + +#if LWIP_IPV6 + if (isV6()) { + int count0 = 0; + for (int i = 0; i < 8; i++) { + uint16_t bit = PP_NTOHS(raw6()[i]); + if (bit || count0 < 0) { + n += p.printf("%x", bit); + if (count0 > 0) + // no more hiding 0 + count0 = -8; + } else + count0++; + if ((i != 7 && count0 < 2) || count0 == 7) + n += p.print(':'); + } + // add a zone if zone-id si non-zero + if (_ip.u_addr.ip6.zone) { + n += p.print('%'); + char if_name[NETIF_NAMESIZE]; + netif_index_to_name(_ip.u_addr.ip6.zone, if_name); + n += p.print(if_name); + } + return n; + } +#endif + + for(int i = 0; i < 4; i++) { + n += p.print((*this)[i], DEC); + if (i != 3) + n += p.print('.'); + } + return n; +} + +String IPAddress::toString() const +{ + StreamString sstr; +#if LWIP_IPV6 + if (isV6()) + sstr.reserve(44); // 8 shorts x 4 chars each + 7 colons + nullterm + '%' + zone-id + else +#endif + sstr.reserve(16); // 4 bytes with 3 chars max + 3 dots + nullterm, or '(IP unset)' + printTo(sstr); + return sstr; +} + +bool IPAddress::isValid(const String& arg) { + return IPAddress().fromString(arg); +} + +bool IPAddress::isValid(const char* arg) { + return IPAddress().fromString(arg); +} + +const IPAddress INADDR46_ANY; // generic "0.0.0.0" for IPv4 & IPv6 +const IPAddress INADDR46_NONE(255,255,255,255); + +void IPAddress::clear() { + (*this) = INADDR46_ANY; +} + +/**************************************/ + +#if LWIP_IPV6 + +bool IPAddress::fromString6(const char *address) { + ip6_addr_t ip6; + if (ip6addr_aton(address, &ip6)) { + setV6(); + memcpy(&this->_ip.u_addr.ip6.addr[0], ip6.addr, 16); + // look for '%' in string + const char *s = address; + while (*s && *s != '%') { s++; } + if (*s == '%') { + // we have a zone id + setZone(netif_name_to_index(s + 1)); + } + return true; + } + return false; +} +#endif // LWIP_IPV6 + // declared one time - as external in IPAddress.h -IPAddress INADDR_NONE(0, 0, 0, 0); +IPAddress INADDR_NONE(0, 0, 0, 0); // TODO diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index 3bedd4f8749..e190c832a5e 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -20,77 +20,190 @@ #ifndef IPAddress_h #define IPAddress_h -#include #include #include +#include -// A class to make it easier to handle and pass around IP addresses +enum IPType +{ + IPv4 = IPADDR_TYPE_V4, + IPv6 = IPADDR_TYPE_V6 +}; class IPAddress: public Printable { private: - union { - uint8_t bytes[4]; // IPv4 address - uint32_t dword; - } _address; + ip_addr_t _ip; // Access the raw byte array containing the address. Because this returns a pointer // to the internal structure rather than a copy of the address this function should only // be used when you know that the usage of the returned uint8_t* will be transient and not // stored. - uint8_t* raw_address() - { - return _address.bytes; + uint8_t* raw_address() { + return reinterpret_cast(&v4()); } + const uint8_t* raw_address() const { + return reinterpret_cast(&v4()); + } + + void ctor32 (uint32_t); public: // Constructors IPAddress(); + IPAddress(const IPAddress& from); IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - IPAddress(uint32_t address); - IPAddress(const uint8_t *address); - virtual ~IPAddress() {} + IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16); + IPAddress(uint32_t address) { *this = address; } + IPAddress(int address) { *this = address; } + IPAddress(const uint8_t *address) { *this = address; } + IPAddress(IPType type, const uint8_t *address); + IPAddress(IPType type, const uint8_t *address, uint8_t zone); bool fromString(const char *address); bool fromString(const String &address) { return fromString(address.c_str()); } // Overloaded cast operator to allow IPAddress objects to be used where a pointer // to a four-byte uint8_t array is expected - operator uint32_t() const - { - return _address.dword; + operator uint32_t() const { return isV4()? v4(): (uint32_t)0; } + operator uint32_t() { return isV4()? v4(): (uint32_t)0; } + + // generic IPv4 wrapper to uint32-view like arduino loves to see it + const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } + uint32_t& v4() { return ip_2_ip4(&_ip)->addr; } + + bool operator==(const IPAddress& addr) const { + return ip_addr_cmp(&_ip, &addr._ip); } - bool operator==(const IPAddress& addr) const - { - return _address.dword == addr._address.dword; + bool operator!=(const IPAddress& addr) const { + return !ip_addr_cmp(&_ip, &addr._ip); + } + bool operator==(uint32_t addr) const { + return isV4() && v4() == addr; + } + // bool operator==(unsigned long addr) const { + // return isV4() && v4() == (uint32_t)addr; + // } + bool operator!=(uint32_t addr) const { + return !(isV4() && v4() == addr); } + // bool operator!=(unsigned long addr) const { + // return isV4() && v4() != (uint32_t)addr; + // } bool operator==(const uint8_t* addr) const; + int operator>>(int n) const { + return isV4()? v4() >> n: 0; + } + // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const - { - return _address.bytes[index]; + uint8_t operator[](int index) const { + if (!isV4()) { + return 0; + } + + return ip4_addr_get_byte_val(*ip_2_ip4(&_ip), index); } - uint8_t& operator[](int index) - { - return _address.bytes[index]; + uint8_t& operator[](int index) { + setV4(); + uint8_t* ptr = reinterpret_cast(&v4()); + return *(ptr + index); } // Overloaded copy operators to allow initialisation of IPAddress objects from other types IPAddress& operator=(const uint8_t *address); IPAddress& operator=(uint32_t address); + IPAddress& operator=(const IPAddress&) = default; + + IPType type() const { return (IPType)_ip.type; } virtual size_t printTo(Print& p) const; String toString() const; + void clear(); + + /* + check if input string(arg) is a valid IPV4 address or not. + return true on valid. + return false on invalid. + */ + static bool isValid(const String& arg); + static bool isValid(const char* arg); + friend class EthernetClass; friend class UDP; friend class Client; friend class Server; friend class DhcpClass; friend class DNSClient; + + operator ip_addr_t () const { return _ip; } + operator const ip_addr_t*() const { return &_ip; } + operator ip_addr_t*() { return &_ip; } + + bool isV4() const { return IP_IS_V4_VAL(_ip); } + void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); } + + bool isLocal() const { return ip_addr_islinklocal(&_ip); } + bool isAny() const { return ip_addr_isany_val(_ip); } + +#if LWIP_IPV6 + IPAddress(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); } + IPAddress(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); } + + IPAddress& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; } + IPAddress& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; } + + uint16_t* raw6() + { + setV6(); + return reinterpret_cast(ip_2_ip6(&_ip)); + } + + const uint16_t* raw6() const + { + return isV6()? reinterpret_cast(ip_2_ip6(&_ip)): nullptr; + } + + // when not IPv6, ip_addr_t == ip4_addr_t so this one would be ambiguous + // required otherwise + operator const ip4_addr_t*() const { return isV4()? ip_2_ip4(&_ip): nullptr; } + + bool isV6() const { return IP_IS_V6_VAL(_ip); } + void setV6() { + IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6); + ip6_addr_clear_zone(ip_2_ip6(&_ip)); + } + inline uint8_t zone() const { return isV6() ? ip_2_ip6(&_ip)->zone : 0; } + void setZone(uint8_t zone) { + if (isV6()) { + ip_2_ip6(&_ip)->zone = zone; + } + } + + +protected: + bool fromString6(const char *address); + +#else /* !LWIP_IPV6 */ + + // allow portable code when IPv6 is not enabled + + uint16_t* raw6() { return nullptr; } + const uint16_t* raw6() const { return nullptr; } + bool isV6() const { return false; } + void setV6() { } + inline uint8_t zone() const { return 0; } + void setZone(uint8_t zone) { } + +#endif + +protected: + bool fromString4(const char *address); }; // changed to extern because const declaration creates copies in BSS of INADDR_NONE for each CPP unit that includes it extern IPAddress INADDR_NONE; +extern IPAddress IN6ADDR_ANY; + #endif diff --git a/idf_component.yml b/idf_component.yml index cb56652e9ed..322ebaabba7 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -29,42 +29,4 @@ dependencies: idf: ">=5.1" # mdns 1.2.1 is necessary to build H2 with no WiFi mdns: "1.2.1" - chmorgan/esp-libhelix-mp3: - version: "1.0.3" - require: public - espressif/esp-zboss-lib: - version: "^1.0.1" - rules: - - if: "target != esp32c2" - espressif/esp-zigbee-lib: - version: "^1.0.1" - rules: - - if: "target != esp32c2" - esp-dsp: - version: "^1.3.4" - rules: - - if: "target != esp32c2" - espressif/esp_rainmaker: - version: "^1.0.0" - rules: - - if: "target != esp32c2" - espressif/rmaker_common: - version: "^1.4.3" - rules: - - if: "target != esp32c2" - espressif/esp_insights: - version: "^1.0.1" - rules: - - if: "target != esp32c2" - espressif/qrcode: - version: "^0.1.0~1" - rules: - - if: "target != esp32c2" joltwallet/littlefs: "^1.10.2" - espressif/esp-sr: - version: "^1.4.2" - rules: - - if: "target in [esp32s3]" -examples: - - path: idf_component_examples/ - diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 40c408ee69a..4ade1a04d7e 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -149,6 +149,9 @@ bool ETHClass::begin(eth_phy_type_t type, uint8_t phy_addr, int mdc, int mdio, i case ETH_PHY_DP83848: phy = esp_eth_phy_new_dp83848(&phy_config); break; + case ETH_PHY_JL1101: + phy = esp_eth_phy_new_jl1101(&phy_config); + break; case ETH_PHY_KSZ8041: phy = esp_eth_phy_new_ksz80xx(&phy_config); break; diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index 7ef39ef561f..c95d69d1689 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -89,7 +89,7 @@ typedef enum { ETH_CLOCK_GPIO0_IN, ETH_CLOCK_GPIO0_OUT, ETH_CLOCK_GPIO16_OUT, ET typedef enum { #if CONFIG_ETH_USE_ESP32_EMAC - ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_RTL8201, ETH_PHY_DP83848, ETH_PHY_KSZ8041, ETH_PHY_KSZ8081, + ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_RTL8201, ETH_PHY_JL1101, ETH_PHY_DP83848, ETH_PHY_KSZ8041, ETH_PHY_KSZ8081, #endif /* CONFIG_ETH_USE_ESP32_EMAC */ #if CONFIG_ETH_SPI_ETHERNET_DM9051 ETH_PHY_DM9051, diff --git a/libraries/HTTPClient/src/HTTPClient.cpp b/libraries/HTTPClient/src/HTTPClient.cpp index 62a9c44901b..019aefdb077 100644 --- a/libraries/HTTPClient/src/HTTPClient.cpp +++ b/libraries/HTTPClient/src/HTTPClient.cpp @@ -31,7 +31,6 @@ #ifdef HTTPCLIENT_1_1_COMPATIBLE #include -#include #endif #include @@ -61,37 +60,6 @@ class TransportTraits } }; -class TLSTraits : public TransportTraits -{ -public: - TLSTraits(const char* CAcert, const char* clicert = nullptr, const char* clikey = nullptr) : - _cacert(CAcert), _clicert(clicert), _clikey(clikey) - { - } - - std::unique_ptr create() override - { - return std::unique_ptr(new WiFiClientSecure()); - } - - bool verify(WiFiClient& client, const char* host) override - { - WiFiClientSecure& wcs = static_cast(client); - if (_cacert == nullptr) { - wcs.setInsecure(); - } else { - wcs.setCACert(_cacert); - wcs.setCertificate(_clicert); - wcs.setPrivateKey(_clikey); - } - return true; - } - -protected: - const char* _cacert; - const char* _clicert; - const char* _clikey; -}; #endif // HTTPCLIENT_1_1_COMPATIBLE /** @@ -197,29 +165,6 @@ bool HTTPClient::begin(WiFiClient &client, String host, uint16_t port, String ur #ifdef HTTPCLIENT_1_1_COMPATIBLE -bool HTTPClient::begin(String url, const char* CAcert) -{ - if(_client && !_tcpDeprecated) { - log_d("mix up of new and deprecated api"); - _canReuse = false; - end(); - } - - clear(); - _port = 443; - if (!beginInternal(url, "https")) { - return false; - } - _secure = true; - _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert)); - if(!_transportTraits) { - log_e("could not create transport traits"); - return false; - } - - return true; -} - /** * parsing the url for all needed parameters * @param url String @@ -322,47 +267,6 @@ bool HTTPClient::begin(String host, uint16_t port, String uri) return true; } -bool HTTPClient::begin(String host, uint16_t port, String uri, const char* CAcert) -{ - if(_client && !_tcpDeprecated) { - log_d("mix up of new and deprecated api"); - _canReuse = false; - end(); - } - - clear(); - _host = host; - _port = port; - _uri = uri; - - if (strlen(CAcert) == 0) { - return false; - } - _secure = true; - _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert)); - return true; -} - -bool HTTPClient::begin(String host, uint16_t port, String uri, const char* CAcert, const char* cli_cert, const char* cli_key) -{ - if(_client && !_tcpDeprecated) { - log_d("mix up of new and deprecated api"); - _canReuse = false; - end(); - } - - clear(); - _host = host; - _port = port; - _uri = uri; - - if (strlen(CAcert) == 0) { - return false; - } - _secure = true; - _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert, cli_cert, cli_key)); - return true; -} #endif // HTTPCLIENT_1_1_COMPATIBLE /** diff --git a/libraries/HTTPClient/src/HTTPClient.h b/libraries/HTTPClient/src/HTTPClient.h index 0058c1ef18c..fc22c842a7c 100644 --- a/libraries/HTTPClient/src/HTTPClient.h +++ b/libraries/HTTPClient/src/HTTPClient.h @@ -34,7 +34,6 @@ #include #include #include -#include /// Cookie jar support #include diff --git a/libraries/Update/src/Updater.cpp b/libraries/Update/src/Updater.cpp index b519b76c380..1e3ef97bbc6 100644 --- a/libraries/Update/src/Updater.cpp +++ b/libraries/Update/src/Updater.cpp @@ -393,6 +393,8 @@ size_t UpdateClass::writeStream(Stream &data) { if((_bufferLen == remaining() || _bufferLen == SPI_FLASH_SEC_SIZE) && !_writeBuffer()) return written; written += toRead; + + delay(1); // Fix solo WDT } return written; } diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index 91247d17386..bd1839c8af6 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -23,6 +23,11 @@ #include #include +#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))) + #define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000) #define WIFI_CLIENT_MAX_WRITE_RETRY (10) #define WIFI_CLIENT_SELECT_TIMEOUT_US (1000000) @@ -217,22 +222,36 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) { return connect(ip,port,_timeout); } + int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms) { + struct sockaddr_storage serveraddr = {}; _timeout = timeout_ms; - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + int sockfd = -1; + +#if LWIP_IPV6 + if (ip.isV6()) { + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; + sockfd = socket(AF_INET6, SOCK_STREAM, 0); + tmpaddr->sin6_family = AF_INET6; + memcpy(tmpaddr->sin6_addr.un.u8_addr, &ip[0], 16); + tmpaddr->sin6_port = htons(port); + tmpaddr->sin6_scope_id = ip.zone(); + } else +#endif + { + struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + tmpaddr->sin_family = AF_INET; + tmpaddr->sin_addr.s_addr = ip; + tmpaddr->sin_port = htons(port); + } if (sockfd < 0) { log_e("socket: %d", errno); return 0; } fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) | O_NONBLOCK ); - uint32_t ip_addr = ip; - struct sockaddr_in serveraddr; - memset((char *) &serveraddr, 0, sizeof(serveraddr)); - serveraddr.sin_family = AF_INET; - memcpy((void *)&serveraddr.sin_addr.s_addr, (const void *)(&ip_addr), 4); - serveraddr.sin_port = htons(port); fd_set fdset; struct timeval tv; FD_ZERO(&fdset); @@ -301,6 +320,19 @@ int WiFiClient::connect(const char *host, uint16_t port) int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout_ms) { + if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) { + ip_addr_t srv6; + if(!WiFiGenericClass::hostByName6(host, srv6)){ + return 0; + } + if (srv6.type == IPADDR_TYPE_V4) { + IPAddress ip(srv6.u_addr.ip4.addr); + return connect(ip, port, timeout_ms); + } else { + IPAddress ip(IPv6, (uint8_t*)&srv6.u_addr.ip6.addr[0]); + return connect(ip, port, timeout_ms); + } + } IPAddress srv((uint32_t)0); if(!WiFiGenericClass::hostByName(host, srv)){ return 0; @@ -562,8 +594,26 @@ IPAddress WiFiClient::remoteIP(int fd) const struct sockaddr_storage addr; socklen_t len = sizeof addr; getpeername(fd, (struct sockaddr*)&addr, &len); - struct sockaddr_in *s = (struct sockaddr_in *)&addr; - return IPAddress((uint32_t)(s->sin_addr.s_addr)); + + // IPv4 socket, old way + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + return IPAddress((uint32_t)(s->sin_addr.s_addr)); + } + +#if LWIP_IPV6 + // IPv6, but it might be IPv4 mapped address + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; + if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { + return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12); + } else { + return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); + } + } +#endif + log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); + return (IPAddress(0,0,0,0)); } uint16_t WiFiClient::remotePort(int fd) const @@ -626,4 +676,3 @@ int WiFiClient::fd() const return clientSocketHandle->fd(); } } - diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 8ef803064c4..c43bf46bc30 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1055,8 +1055,8 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_CONNECTED) { WiFiSTAClass::_setStatus(WL_IDLE_STATUS); setStatusBits(STA_CONNECTED_BIT); - - //esp_netif_create_ip6_linklocal(esp_netifs[ESP_IF_WIFI_STA]); + if (getStatusBits() & WIFI_WANT_IP6_BIT) + esp_netif_create_ip6_linklocal(esp_netifs[ESP_IF_WIFI_STA]); } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { uint8_t reason = event->event_info.wifi_sta_disconnected.reason; // Reason 0 causes crash, use reason 1 (UNSPECIFIED) instead @@ -1577,8 +1577,27 @@ static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param) } /** - * Resolve the given hostname to an IP address. If passed hostname is an IP address, it will be parsed into IPAddress structure. - * @param aHostname Name to be resolved or string containing IP address + * IPv6 compatible DNS callback + * @param name + * @param ipaddr + * @param callback_arg + */ +static void wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg *)callback_arg; + + if(ipaddr && !msg->result) { + msg->ip_addr = *ipaddr; + msg->result = 1; + } else { + msg->result = -1; + } + xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT); +} + +/** + * Resolve the given hostname to an IP address. + * @param aHostname Name to be resolved * @param aResult IPAddress structure to store the returned IP address * @return 1 if aIPAddrString was successfully converted to an IP address, * else error code @@ -1608,6 +1627,37 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) return (uint32_t)aResult != 0; } +/** + * Resolve the given hostname to an IP6 address. + * @param aHostname Name to be resolved + * @param aResult IPv6Address structure to store the returned IP address + * @return 1 if aHostname was successfully converted to an IP address, + * else error code + */ +int WiFiGenericClass::hostByName6(const char* aHostname, ip_addr_t& aResult) +{ + ip_addr_t addr; + struct dns_api_msg arg; + + memset(&arg, 0x0, sizeof(arg)); + waitStatusBits(WIFI_DNS_IDLE_BIT, 16000); + clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT); + + err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns6_found_callback, + &arg, LWIP_DNS_ADDRTYPE_IPV6_IPV4); + if(err == ERR_OK) { + aResult = addr; + } else if(err == ERR_INPROGRESS) { + waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] + clearStatusBits(WIFI_DNS_DONE_BIT); + if (arg.result == 1) { + aResult = arg.ip_addr; + } + } + setStatusBits(WIFI_DNS_IDLE_BIT); + return (uint32_t)err == ERR_OK || (err == ERR_INPROGRESS && arg.result == 1); +} + IPAddress WiFiGenericClass::calculateNetworkID(IPAddress ip, IPAddress subnet) { IPAddress networkID; diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 38396f5a72e..ce723409eca 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -141,6 +141,7 @@ static const int WIFI_SCANNING_BIT = BIT11; static const int WIFI_SCAN_DONE_BIT= BIT12; static const int WIFI_DNS_IDLE_BIT = BIT13; static const int WIFI_DNS_DONE_BIT = BIT14; +static const int WIFI_WANT_IP6_BIT = BIT15; typedef enum { WIFI_RX_ANT0 = 0, @@ -154,6 +155,11 @@ typedef enum { WIFI_TX_ANT_AUTO } wifi_tx_ant_t; +struct dns_api_msg { + ip_addr_t ip_addr; + int result; +}; + class WiFiGenericClass { public: @@ -196,6 +202,7 @@ class WiFiGenericClass static const char * getHostname(); static bool setHostname(const char * hostname); static bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); } + static int hostByName6(const char *aHostname, ip_addr_t& aResult); static esp_err_t _eventCallback(arduino_event_t *event); diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index 3d69e481293..9e7f03c6531 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -30,6 +30,7 @@ WiFiMulti::WiFiMulti() { + ipv6_support = false; } WiFiMulti::~WiFiMulti() @@ -160,6 +161,8 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) log_i("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); + if (ipv6_support == true) + WiFi.IPv6(true); status = WiFi.status(); auto startTime = millis(); @@ -202,3 +205,7 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) return status; } + +void WiFiMulti::IPv6(bool state) { + ipv6_support = state; +} diff --git a/libraries/WiFi/src/WiFiMulti.h b/libraries/WiFi/src/WiFiMulti.h index 38ddb5d9f95..bbeb78dc860 100644 --- a/libraries/WiFi/src/WiFiMulti.h +++ b/libraries/WiFi/src/WiFiMulti.h @@ -42,10 +42,12 @@ class WiFiMulti bool addAP(const char* ssid, const char *passphrase = NULL); + void IPv6(bool state); uint8_t run(uint32_t connectTimeout=5000); private: std::vector APlist; + bool ipv6_support; }; #endif /* WIFICLIENTMULTI_H_ */ diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index 505940015f9..1cd4cfafa4b 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -153,88 +153,6 @@ wl_status_t WiFiSTAClass::status() return (wl_status_t)xEventGroupClearBits(_sta_status_group, 0); } -/** - * Start Wifi connection with a WPA2 Enterprise AP - * if passphrase is set the most secure supported mode will be automatically selected - * @param ssid const char* Pointer to the SSID string. - * @param method wpa2_method_t The authentication method of WPA2 (WPA2_AUTH_TLS, WPA2_AUTH_PEAP, WPA2_AUTH_TTLS) - * @param wpa2_identity const char* Pointer to the entity - * @param wpa2_username const char* Pointer to the username - * @param password const char * Pointer to the password. - * @param ca_pem const char* Pointer to a string with the contents of a .pem file with CA cert - * @param client_crt const char* Pointer to a string with the contents of a .crt file with client cert - * @param client_key const char* Pointer to a string with the contants of a .key file with client key - * @param bssid uint8_t[6] Optional. BSSID / MAC of AP - * @param channel Optional. Channel of AP - * @param connect Optional. call connect - * @return - */ -wl_status_t WiFiSTAClass::begin(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity, const char* wpa2_username, const char *wpa2_password, const char* ca_pem, const char* client_crt, const char* client_key, int32_t channel, const uint8_t* bssid, bool connect) -{ - if(!WiFi.enableSTA(true)) { - log_e("STA enable failed!"); - return WL_CONNECT_FAILED; - } - - if(!wpa2_ssid || *wpa2_ssid == 0x00 || strlen(wpa2_ssid) > 32) { - log_e("SSID too long or missing!"); - return WL_CONNECT_FAILED; - } - - if(wpa2_identity && strlen(wpa2_identity) > 64) { - log_e("identity too long!"); - return WL_CONNECT_FAILED; - } - - if(wpa2_username && strlen(wpa2_username) > 64) { - log_e("username too long!"); - return WL_CONNECT_FAILED; - } - - if(wpa2_password && strlen(wpa2_password) > 64) { - log_e("password too long!"); - } - - if(ca_pem) { -#if __has_include ("esp_eap_client.h") - esp_eap_client_set_ca_cert((uint8_t *)ca_pem, strlen(ca_pem)); -#else - esp_wifi_sta_wpa2_ent_set_ca_cert((uint8_t *)ca_pem, strlen(ca_pem)); -#endif - } - - if(client_crt) { -#if __has_include ("esp_eap_client.h") - esp_eap_client_set_certificate_and_key((uint8_t *)client_crt, strlen(client_crt), (uint8_t *)client_key, strlen(client_key), NULL, 0); -#else - esp_wifi_sta_wpa2_ent_set_cert_key((uint8_t *)client_crt, strlen(client_crt), (uint8_t *)client_key, strlen(client_key), NULL, 0); -#endif - } - -#if __has_include ("esp_eap_client.h") - esp_eap_client_set_identity((uint8_t *)wpa2_identity, strlen(wpa2_identity)); -#else - esp_wifi_sta_wpa2_ent_set_identity((uint8_t *)wpa2_identity, strlen(wpa2_identity)); -#endif - if(method == WPA2_AUTH_PEAP || method == WPA2_AUTH_TTLS) { -#if __has_include ("esp_eap_client.h") - esp_eap_client_set_username((uint8_t *)wpa2_username, strlen(wpa2_username)); - esp_eap_client_set_password((uint8_t *)wpa2_password, strlen(wpa2_password)); -#else - esp_wifi_sta_wpa2_ent_set_username((uint8_t *)wpa2_username, strlen(wpa2_username)); - esp_wifi_sta_wpa2_ent_set_password((uint8_t *)wpa2_password, strlen(wpa2_password)); -#endif - } -#if __has_include ("esp_eap_client.h") - esp_wifi_sta_enterprise_enable(); //set config settings to enable function -#else - esp_wifi_sta_wpa2_ent_enable(); //set config settings to enable function -#endif - WiFi.begin(wpa2_ssid); //connect to wifi - - return status(); -} - /** * Start Wifi connection * if passphrase is set the most secure supported mode will be automatically selected @@ -373,7 +291,6 @@ bool WiFiSTAClass::disconnect(bool wifioff, bool eraseap) wifi_sta_config(&conf); if(WiFi.getMode() & WIFI_MODE_STA){ - _useStaticIp = false; if(eraseap){ if(esp_wifi_set_config((wifi_interface_t)ESP_IF_WIFI_STA, &conf)){ log_e("clear config failed!"); @@ -816,6 +733,19 @@ bool WiFiSTAClass::enableIpV6() return esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)) == ESP_OK; } +/** + * Enable IPv6 support on the station interface. + * @return true on success + */ +bool WiFiSTAClass::IPv6(bool state) +{ + if (state) + WiFiGenericClass::setStatusBits(WIFI_WANT_IP6_BIT); + else + WiFiGenericClass::clearStatusBits(WIFI_WANT_IP6_BIT); + return true; +} + /** * Get the station interface IPv6 address. * @return IPv6Address diff --git a/libraries/WiFi/src/WiFiSTA.h b/libraries/WiFi/src/WiFiSTA.h index 07f01922cef..12e2f0bd4a4 100644 --- a/libraries/WiFi/src/WiFiSTA.h +++ b/libraries/WiFi/src/WiFiSTA.h @@ -94,6 +94,7 @@ class WiFiSTAClass uint8_t subnetCIDR(); bool enableIpV6(); + bool IPv6(bool state); IPv6Address localIPv6(); // STA WiFi info diff --git a/libraries/WiFi/src/WiFiServer.cpp b/libraries/WiFi/src/WiFiServer.cpp index ef59cf14d6d..2e0aa6990aa 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -51,8 +51,8 @@ WiFiClient WiFiServer::accept(){ _accepted_sockfd = -1; } else { - struct sockaddr_in _client; - int cs = sizeof(struct sockaddr_in); + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); #ifdef ESP_IDF_VERSION_MAJOR client_sock = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); #else @@ -80,14 +80,23 @@ void WiFiServer::begin(uint16_t port, int enable){ if(port){ _port = port; } - struct sockaddr_in server; - sockfd = socket(AF_INET , SOCK_STREAM, 0); + struct sockaddr_in6 server; + sockfd = socket(AF_INET6 , SOCK_STREAM, 0); if (sockfd < 0) return; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); - server.sin_family = AF_INET; - server.sin_addr.s_addr = _addr; - server.sin_port = htons(_port); + server.sin6_family = AF_INET6; + memset(server.sin6_addr.s6_addr, 0x0, 16); + if (_addr.type() == IPv4) { + // log_e("---------------- IPv4"); + memcpy(server.sin6_addr.s6_addr+12, (uint8_t*)&_addr[0], 4); + server.sin6_addr.s6_addr[10] = 0xFF; + server.sin6_addr.s6_addr[11] = 0xFF; + } else { + // log_e("---------------- IPv6"); + memcpy(server.sin6_addr.s6_addr, (uint8_t*)&_addr[0], 16); + } + server.sin6_port = htons(_port); if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) return; if(listen(sockfd , _max_clients) < 0) @@ -110,8 +119,8 @@ bool WiFiServer::hasClient() { if (_accepted_sockfd >= 0) { return true; } - struct sockaddr_in _client; - int cs = sizeof(struct sockaddr_in); + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); #ifdef ESP_IDF_VERSION_MAJOR _accepted_sockfd = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); #else @@ -140,4 +149,3 @@ void WiFiServer::close(){ void WiFiServer::stop(){ end(); } - diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index b9db726b9b7..2c2ebc0b8f2 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -37,7 +37,6 @@ class WiFiServer : public Server { public: void listenOnLocalhost(){} - // _addr(INADDR_ANY) is the same as _addr() ==> 0.0.0.0 WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { log_v("WiFiServer::WiFiServer(port=%d, ...)", port); } diff --git a/libraries/WiFi/src/WiFiUdp.cpp b/libraries/WiFi/src/WiFiUdp.cpp index 0d75739afb9..9bb45a3f62a 100644 --- a/libraries/WiFi/src/WiFiUdp.cpp +++ b/libraries/WiFi/src/WiFiUdp.cpp @@ -50,7 +50,11 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ return 0; } +#if LWIP_IPV6 + if ((udp_server=socket(address.isV6() ? AF_INET6 : AF_INET, SOCK_DGRAM, 0)) == -1){ +#else if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ +#endif log_e("could not create socket: %d", errno); return 0; } @@ -62,12 +66,30 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ return 0; } - struct sockaddr_in addr; - memset((char *) &addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(server_port); - addr.sin_addr.s_addr = (in_addr_t)address; - if(bind(udp_server , (struct sockaddr*)&addr, sizeof(addr)) == -1){ + struct sockaddr_storage serveraddr = {}; + size_t sock_size = 0; +#if LWIP_IPV6 + if (address.isV6()) { + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; + ip_addr_t * ip_addr = (ip_addr_t*) address; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); + tmpaddr->sin6_family = AF_INET6; + tmpaddr->sin6_port = htons(server_port); + tmpaddr->sin6_scope_id = ip_addr->u_addr.ip6.zone; + inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(ip_addr)); + tmpaddr->sin6_flowinfo = 0; + sock_size = sizeof(sockaddr_in6); + } else +#endif + { + struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); + tmpaddr->sin_family = AF_INET; + tmpaddr->sin_port = htons(server_port); + tmpaddr->sin_addr.s_addr = (in_addr_t)address; + sock_size = sizeof(sockaddr_in); + } + if(bind(udp_server , (sockaddr*)&serveraddr, sock_size) == -1){ log_e("could not bind socket: %d", errno); stop(); return 0; @@ -77,23 +99,47 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ } uint8_t WiFiUDP::begin(uint16_t p){ - return begin(IPAddress(INADDR_ANY), p); + return begin(IPAddress(), p); } uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){ - if(begin(IPAddress(INADDR_ANY), p)){ - if((uint32_t)a != 0){ - struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = (in_addr_t)a; - mreq.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + if(begin(IPAddress(), p)){ + ip_addr_t * ip_addr = (ip_addr_t*) a; + if (ip_addr_ismulticast(ip_addr)) { +#if LWIP_IPV6 + if (IP_IS_V6_VAL(*ip_addr)) { + struct ipv6_mreq mreq; + bool joined = false; + inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(ip_addr)); + + // iterate on each interface + for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { + mreq.ipv6mr_interface = intf->num + 1; + if (intf->name[0] != 'l' || intf->name[1] != 'o') { // skip 'lo' local interface + int ret = setsockopt(udp_server, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + if (ret >= 0) { joined = true; } + } + } + if (!joined) { log_e("could not join igmp: %d", errno); stop(); return 0; + } + } else +#endif + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = (in_addr_t)a; + mreq.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + log_e("could not join igmp: %d", errno); + stop(); + return 0; + } } multicast_ip = a; + return 1; } - return 1; } return 0; } @@ -111,19 +157,37 @@ void WiFiUDP::stop(){ } if(udp_server == -1) return; - if((uint32_t)multicast_ip != 0){ - struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip; - mreq.imr_interface.s_addr = (in_addr_t)0; - setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); - multicast_ip = IPAddress(INADDR_ANY); + ip_addr_t * mcast_addr = (ip_addr_t*) multicast_ip; + if (!ip_addr_isany(mcast_addr)) { +#if LWIP_IPV6 + if (IP_IS_V6(mcast_addr)) { + struct ipv6_mreq mreq; + inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(mcast_addr)); + + // iterate on each interface + for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { + mreq.ipv6mr_interface = intf->num + 1; + if (intf->name[0] != 'l' || intf->name[1] != 'o') { // skip 'lo' local interface + setsockopt(udp_server, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)); + } + } + } else +#endif + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip; + mreq.imr_interface.s_addr = (in_addr_t)0; + setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); + } + // now common code for v4/v6 + multicast_ip = IPAddress(); } close(udp_server); udp_server = -1; } int WiFiUDP::beginMulticastPacket(){ - if(!server_port || multicast_ip == IPAddress(INADDR_ANY)) + if(!server_port || multicast_ip == IPAddress()) return 0; remote_ip = multicast_ip; remote_port = server_port; @@ -176,14 +240,29 @@ int WiFiUDP::beginPacket(const char *host, uint16_t port){ } int WiFiUDP::endPacket(){ - struct sockaddr_in recipient; - recipient.sin_addr.s_addr = (uint32_t)remote_ip; - recipient.sin_family = AF_INET; - recipient.sin_port = htons(remote_port); - int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); - if(sent < 0){ - log_e("could not send data: %d", errno); - return 0; + + if (remote_ip.isV4()) { + struct sockaddr_in recipient; + recipient.sin_addr.s_addr = (uint32_t)remote_ip; + recipient.sin_family = AF_INET; + recipient.sin_port = htons(remote_port); + int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); + if(sent < 0){ + log_e("could not send data: %d", errno); + return 0; + } + } else { + struct sockaddr_in6 recipient; + recipient.sin6_flowinfo = 0; + recipient.sin6_addr = *(in6_addr*)(ip_addr_t*)remote_ip; + recipient.sin6_family = AF_INET6; + recipient.sin6_port = htons(remote_port); + recipient.sin6_scope_id = remote_ip.zone(); + int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); + if(sent < 0){ + log_e("could not send data: %d", errno); + return 0; + } } return 1; } @@ -207,13 +286,14 @@ size_t WiFiUDP::write(const uint8_t *buffer, size_t size){ int WiFiUDP::parsePacket(){ if(rx_buffer) return 0; - struct sockaddr_in si_other; - int slen = sizeof(si_other) , len; + struct sockaddr_storage si_other_storage; // enough storage for v4 and v6 + socklen_t slen = sizeof(sockaddr_storage); + int len; char *buf = (char *)malloc(1460); if(!buf) { return 0; } - if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){ + if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other_storage, (socklen_t *)&slen)) == -1){ free(buf); if(errno == EWOULDBLOCK){ return 0; @@ -221,8 +301,28 @@ int WiFiUDP::parsePacket(){ log_e("could not receive data: %d", errno); return 0; } - remote_ip = IPAddress(si_other.sin_addr.s_addr); - remote_port = ntohs(si_other.sin_port); + if (si_other_storage.ss_family == AF_INET) { + struct sockaddr_in &si_other = (sockaddr_in&) si_other_storage; + remote_ip = IPAddress(si_other.sin_addr.s_addr); + remote_port = ntohs(si_other.sin_port); + } +#if LWIP_IPV6 + else if (si_other_storage.ss_family == AF_INET6) { + struct sockaddr_in6 &si_other = (sockaddr_in6&) si_other_storage; + remote_ip = IPAddress(IPv6, (uint8_t*)&si_other.sin6_addr, si_other.sin6_scope_id); // force IPv6 + ip_addr_t *ip_addr = (ip_addr_t*) remote_ip; + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(*ip_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(ip_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(ip_addr), ip_2_ip6(ip_addr)); + IP_SET_TYPE_VAL(*ip_addr, IPADDR_TYPE_V4); + } + remote_port = ntohs(si_other.sin6_port); + } +#endif // LWIP_IPV6=1 + else { + remote_ip = *IP_ADDR_ANY; + remote_port = 0; + } if (len > 0) { rx_buffer = new(std::nothrow) cbuf(len); rx_buffer->write(buf, len); diff --git a/libraries/WiFiClientSecure/src/ssl_client.cpp b/libraries/WiFiClientSecure/src/ssl_client.cpp index 8dcf05877ba..faa594f31fa 100644 --- a/libraries/WiFiClientSecure/src/ssl_client.cpp +++ b/libraries/WiFiClientSecure/src/ssl_client.cpp @@ -21,7 +21,7 @@ #include "WiFi.h" #if !defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && !defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) -# warning "Please call `idf.py menuconfig` then go to Component config -> mbedTLS -> TLS Key Exchange Methods -> Enable pre-shared-key ciphersuites and then check `Enable PSK based cyphersuite modes`. Save and Quit." +//# warning "Please call `idf.py menuconfig` then go to Component config -> mbedTLS -> TLS Key Exchange Methods -> Enable pre-shared-key ciphersuites and then check `Enable PSK based cyphersuite modes`. Save and Quit." #else const char *pers = "esp32-tls"; diff --git a/tools/platformio-build.py b/tools/platformio-build.py index e9dc5387187..ae444a30cc6 100644 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -25,7 +25,6 @@ # Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py from os.path import abspath, basename, isdir, isfile, join -from copy import deepcopy from SCons.Script import DefaultEnvironment, SConscript env = DefaultEnvironment() @@ -37,7 +36,7 @@ ) FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") -FRAMEWORK_LIBS_DIR = platform.get_package_dir("framework-arduinoespressif32-libs") +FRAMEWORK_LIBS_DIR = join(FRAMEWORK_DIR, "tools", "esp32-arduino-libs") assert isdir(FRAMEWORK_DIR) @@ -101,8 +100,9 @@ def generate_bootloader_image(bootloader_elf): env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', "--chip", build_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_config.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), @@ -176,9 +176,14 @@ def add_tinyuf2_extra_image(): libs = [] variants_dir = join(FRAMEWORK_DIR, "variants") +try: + build_variants_dir = join(board_config.get("build.variants_dir")) +except: + build_variants_dir="" if "build.variants_dir" in board_config: - variants_dir = join("$PROJECT_DIR", board_config.get("build.variants_dir")) + if len(build_variants_dir) > 1: + variants_dir = join("$PROJECT_DIR", board_config.get("build.variants_dir")) if "build.variant" in board_config: env.Append(CPPPATH=[join(variants_dir, board_config.get("build.variant"))]) @@ -201,6 +206,15 @@ def add_tinyuf2_extra_image(): # Process framework extra images # +# Tasmota places extra images "safeboot" in custom variants folder in project directory +build_name = join(board_config.get("name")) +if len(build_variants_dir) > 1: + EXTRA_IMG_DIR = join(variants_dir) +else: + EXTRA_IMG_DIR = FRAMEWORK_DIR + if "tasmota" in build_name.lower(): + EXTRA_IMG_DIR = join(EXTRA_IMG_DIR, "variants", "tasmota") + env.Append( LIBSOURCE_DIRS=[join(FRAMEWORK_DIR, "libraries")], FLASH_EXTRA_IMAGES=[ @@ -212,7 +226,7 @@ def add_tinyuf2_extra_image(): ("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin")), ] + [ - (offset, join(FRAMEWORK_DIR, img)) + (offset, join(EXTRA_IMG_DIR, img)) for offset, img in board_config.get("upload.arduino.flash_extra_images", []) ], ) @@ -239,13 +253,3 @@ def add_tinyuf2_extra_image(): ), ) env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", partition_table) - -# -# Adjust the `esptoolpy` command in the `ElfToBin` builder with firmware checksum offset -# - -action = deepcopy(env["BUILDERS"]["ElfToBin"].action) -action.cmd_list = env["BUILDERS"]["ElfToBin"].action.cmd_list.replace( - "-o", "--elf-sha256-offset 0xb0 -o" -) -env["BUILDERS"]["ElfToBin"].action = action