diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index c27259c4a..ec0d460d8 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -37,6 +37,7 @@ extern "C" { #include "binary.h" #include "esp8266_peri.h" #include "twi.h" + #include "core_esp8266_features.h" #include "core_esp8266_version.h" @@ -125,15 +126,11 @@ void timer0_isr_init(void); void timer0_attachInterrupt(timercallback userFunc); void timer0_detachInterrupt(void); -// Use stdlib abs() and round() to avoid issues with the C++ libraries #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) #define radians(deg) ((deg)*DEG_TO_RAD) #define degrees(rad) ((rad)*RAD_TO_DEG) #define sq(x) ((x)*(x)) -void ets_intr_lock(); -void ets_intr_unlock(); - #define interrupts() xt_rsil(0) #define noInterrupts() xt_rsil(15) @@ -162,11 +159,12 @@ typedef uint16_t word; typedef bool boolean; typedef uint8_t byte; +void ets_intr_lock(); +void ets_intr_unlock(); + void init(void); void initVariant(void); -int atexit(void (*func)()) __attribute__((weak)); - void pinMode(uint8_t pin, uint8_t mode); void digitalWrite(uint8_t pin, uint8_t val); int digitalRead(uint8_t pin); @@ -212,21 +210,20 @@ void optimistic_yield(uint32_t interval_us); } // extern "C" #endif +// undefine stdlib's definitions when encountered, provide abs that supports floating point for C code +#ifndef __cplusplus +#undef abs +#define abs(x) ({ __typeof__(x) _x = (x); _x > 0 ? _x : -_x; }) +#undef round +#define round(x) ({ __typeof__(x) _x = (x); _x >= 0 ? (long)(_x + 0.5) : (long)(_x - 0.5); }) +#endif // ifndef __cplusplus - +// from this point onward, we need to configure the c++ environment #ifdef __cplusplus #include +#include #include -#include - -#include "WCharacter.h" -#include "WString.h" - -#include "HardwareSerial.h" -#include "Esp.h" -#include "Updater.h" -#include "debug.h" using std::min; using std::max; @@ -234,6 +231,10 @@ using std::round; using std::isinf; using std::isnan; +// Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries +using std::abs; +using std::round; + #define _min(a,b) ({ decltype(a) _a = (a); decltype(b) _b = (b); _a < _b? _a : _b; }) #define _max(a,b) ({ decltype(a) _a = (a); decltype(b) _b = (b); _a > _b? _a : _b; }) @@ -273,8 +274,19 @@ inline void configTzTime(const char* tz, const char* server1, configTime(tz, server1, server2, server3); } +// Everything we expect to be implicitly loaded for the sketch +#include + +#include "WCharacter.h" +#include "WString.h" + +#include "HardwareSerial.h" +#include "Esp.h" +#include "Updater.h" + #endif // __cplusplus +#include "debug.h" #include "pins_arduino.h" #endif diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index e3dae810a..60990103f 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -26,7 +26,9 @@ #include "MD5Builder.h" #include "umm_malloc/umm_malloc.h" #include "cont.h" + #include "coredecls.h" +#include extern "C" { #include "user_interface.h" @@ -40,11 +42,6 @@ extern struct rst_info resetInfo; #ifndef PUYA_SUPPORT #define PUYA_SUPPORT 1 #endif -#ifndef PUYA_BUFFER_SIZE - // Good alternative for buffer size is: SPI_FLASH_SEC_SIZE (= 4k) - // Always use a multiple of flash page size (256 bytes) - #define PUYA_BUFFER_SIZE 256 -#endif /** * User-defined Literals @@ -666,11 +663,14 @@ static SpiFlashOpResult spi_flash_write_puya(uint32_t offset, uint32_t *data, si if (data == nullptr) { return SPI_FLASH_RESULT_ERR; } + if (size % 4 != 0) { + return SPI_FLASH_RESULT_ERR; + } // PUYA flash chips need to read existing data, update in memory and write modified data again. static uint32_t *flash_write_puya_buf = nullptr; if (flash_write_puya_buf == nullptr) { - flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE); + flash_write_puya_buf = (uint32_t*) malloc(FLASH_PAGE_SIZE); // No need to ever free this, since the flash chip will never change at runtime. if (flash_write_puya_buf == nullptr) { // Memory could not be allocated. @@ -684,45 +684,261 @@ static SpiFlashOpResult spi_flash_write_puya(uint32_t offset, uint32_t *data, si uint32_t pos = offset; while (bytesLeft > 0 && rc == SPI_FLASH_RESULT_OK) { size_t bytesNow = bytesLeft; - if (bytesNow > PUYA_BUFFER_SIZE) { - bytesNow = PUYA_BUFFER_SIZE; - bytesLeft -= PUYA_BUFFER_SIZE; + if (bytesNow > FLASH_PAGE_SIZE) { + bytesNow = FLASH_PAGE_SIZE; + bytesLeft -= FLASH_PAGE_SIZE; } else { bytesLeft = 0; } - size_t bytesAligned = (bytesNow + 3) & ~3; - rc = spi_flash_read(pos, flash_write_puya_buf, bytesAligned); + rc = spi_flash_read(pos, flash_write_puya_buf, bytesNow); if (rc != SPI_FLASH_RESULT_OK) { return rc; } - for (size_t i = 0; i < bytesAligned / 4; ++i) { + for (size_t i = 0; i < bytesNow / 4; ++i) { flash_write_puya_buf[i] &= *ptr; ++ptr; } - rc = spi_flash_write(pos, flash_write_puya_buf, bytesAligned); + rc = spi_flash_write(pos, flash_write_puya_buf, bytesNow); pos += bytesNow; } return rc; } #endif -bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { - SpiFlashOpResult rc = SPI_FLASH_RESULT_OK; +bool EspClass::flashReplaceBlock(uint32_t address, const uint8_t *value, uint32_t byteCount) { + uint32_t alignedAddress = (address & ~3); + uint32_t alignmentOffset = address - alignedAddress; + + if (alignedAddress != ((address + byteCount - 1) & ~3)) { + // Only one 4 byte block is supported + return false; + } #if PUYA_SUPPORT if (getFlashChipVendorId() == SPI_FLASH_VENDOR_PUYA) { - rc = spi_flash_write_puya(offset, data, size); + uint8_t tempData[4] __attribute__((aligned(4))); + if (spi_flash_read(alignedAddress, (uint32_t *)tempData, 4) != SPI_FLASH_RESULT_OK) { + return false; + } + for (size_t i = 0; i < byteCount; i++) { + tempData[i + alignmentOffset] &= value[i]; + } + if (spi_flash_write(alignedAddress, (uint32_t *)tempData, 4) != SPI_FLASH_RESULT_OK) { + return false; + } } else -#endif +#endif // PUYA_SUPPORT { - rc = spi_flash_write(offset, data, size); + uint32_t tempData; + if (spi_flash_read(alignedAddress, &tempData, 4) != SPI_FLASH_RESULT_OK) { + return false; + } + memcpy((uint8_t *)&tempData + alignmentOffset, value, byteCount); + if (spi_flash_write(alignedAddress, &tempData, 4) != SPI_FLASH_RESULT_OK) { + return false; + } + } + return true; +} + +size_t EspClass::flashWriteUnalignedMemory(uint32_t address, const uint8_t *data, size_t size) { + size_t sizeLeft = (size & ~3); + size_t currentOffset = 0; + // Memory is unaligned, so we need to copy it to an aligned buffer + uint32_t alignedData[FLASH_PAGE_SIZE / sizeof(uint32_t)] __attribute__((aligned(4))); + // Handle page boundary + bool pageBreak = ((address % 4) != 0) && ((address / FLASH_PAGE_SIZE) != ((address + sizeLeft - 1) / FLASH_PAGE_SIZE)); + + if (pageBreak) { + size_t byteCount = 4 - (address % 4); + + if (!flashReplaceBlock(address, data, byteCount)) { + return 0; + } + // We will now have aligned address, so we can cross page boundaries + currentOffset += byteCount; + // Realign size to 4 + sizeLeft = (size - byteCount) & ~3; + } + + while (sizeLeft) { + size_t willCopy = std::min(sizeLeft, sizeof(alignedData)); + memcpy(alignedData, data + currentOffset, willCopy); + // We now have address, data and size aligned to 4 bytes, so we can use aligned write + if (!flashWrite(address + currentOffset, alignedData, willCopy)) + { + return 0; + } + sizeLeft -= willCopy; + currentOffset += willCopy; + } + + return currentOffset; +} + +bool EspClass::flashWritePageBreak(uint32_t address, const uint8_t *data, size_t size) { + if (size > 4) { + return false; + } + size_t pageLeft = FLASH_PAGE_SIZE - (address % FLASH_PAGE_SIZE); + size_t offset = 0; + size_t sizeLeft = size; + if (pageLeft > 3) { + return false; + } + + if (!flashReplaceBlock(address, data, pageLeft)) { + return false; + } + offset += pageLeft; + sizeLeft -= pageLeft; + // We replaced last 4-byte block of the page, now we write the remainder in next page + if (!flashReplaceBlock(address + offset, data + offset, sizeLeft)) { + return false; + } + return true; +} + +bool EspClass::flashWrite(uint32_t address, const uint32_t *data, size_t size) { + SpiFlashOpResult rc = SPI_FLASH_RESULT_OK; + bool pageBreak = ((address % 4) != 0 && (address / FLASH_PAGE_SIZE) != ((address + size - 1) / FLASH_PAGE_SIZE)); + + if ((uintptr_t)data % 4 != 0 || size % 4 != 0 || pageBreak) { + return false; + } +#if PUYA_SUPPORT + if (getFlashChipVendorId() == SPI_FLASH_VENDOR_PUYA) { + rc = spi_flash_write_puya(address, const_cast(data), size); + } + else +#endif // PUYA_SUPPORT + { + rc = spi_flash_write(address, const_cast(data), size); } return rc == SPI_FLASH_RESULT_OK; } -bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size) { - auto rc = spi_flash_read(offset, (uint32_t*) data, size); - return rc == SPI_FLASH_RESULT_OK; +bool EspClass::flashWrite(uint32_t address, const uint8_t *data, size_t size) { + if (size == 0) { + return true; + } + + size_t sizeLeft = size & ~3; + size_t currentOffset = 0; + + if (sizeLeft) { + if ((uintptr_t)data % 4 != 0) { + size_t written = flashWriteUnalignedMemory(address, data, size); + if (!written) { + return false; + } + currentOffset += written; + sizeLeft -= written; + } else { + bool pageBreak = ((address % 4) != 0 && (address / FLASH_PAGE_SIZE) != ((address + sizeLeft - 1) / FLASH_PAGE_SIZE)); + + if (pageBreak) { + while (sizeLeft) { + // We cannot cross page boundary, but the write must be 4 byte aligned, + // so this is the maximum amount we can write + size_t pageBoundary = (FLASH_PAGE_SIZE - ((address + currentOffset) % FLASH_PAGE_SIZE)) & ~3; + + if (sizeLeft > pageBoundary) { + // Aligned write up to page boundary + if (!flashWrite(address + currentOffset, (uint32_t *)(data + currentOffset), pageBoundary)) { + return false; + } + currentOffset += pageBoundary; + sizeLeft -= pageBoundary; + // Cross the page boundary + if (!flashWritePageBreak(address + currentOffset, data + currentOffset, 4)) { + return false; + } + currentOffset += 4; + sizeLeft -= 4; + } else { + // We do not cross page boundary + if (!flashWrite(address + currentOffset, (uint32_t *)(data + currentOffset), sizeLeft)) { + return false; + } + currentOffset += sizeLeft; + sizeLeft = 0; + } + } + } else { + // Pointer is properly aligned and write does not cross page boundary, + // so use aligned write + if (!flashWrite(address, (uint32_t *)data, sizeLeft)) { + return false; + } + currentOffset = sizeLeft; + sizeLeft = 0; + } + } + } + sizeLeft = size - currentOffset; + if (sizeLeft > 0) { + // Size was not aligned, so we have some bytes left to write, we also need to recheck for + // page boundary crossing + bool pageBreak = ((address % 4) != 0 && (address / FLASH_PAGE_SIZE) != ((address + sizeLeft - 1) / FLASH_PAGE_SIZE)); + + if (pageBreak) { + // Cross the page boundary + if (!flashWritePageBreak(address + currentOffset, data + currentOffset, sizeLeft)) { + return false; + } + } else { + // Just write partial block + flashReplaceBlock(address + currentOffset, data + currentOffset, sizeLeft); + } + } + + return true; +} + +bool EspClass::flashRead(uint32_t address, uint8_t *data, size_t size) { + size_t sizeAligned = size & ~3; + size_t currentOffset = 0; + + if ((uintptr_t)data % 4 != 0) { + uint32_t alignedData[FLASH_PAGE_SIZE / sizeof(uint32_t)] __attribute__((aligned(4))); + size_t sizeLeft = sizeAligned; + + while (sizeLeft) { + size_t willCopy = std::min(sizeLeft, sizeof(alignedData)); + // We read to our aligned buffer and then copy to data + if (!flashRead(address + currentOffset, alignedData, willCopy)) + { + return false; + } + memcpy(data + currentOffset, alignedData, willCopy); + sizeLeft -= willCopy; + currentOffset += willCopy; + } + } else { + // Pointer is properly aligned, so use aligned read + if (!flashRead(address, (uint32_t *)data, sizeAligned)) { + return false; + } + currentOffset = sizeAligned; + } + + if (currentOffset < size) { + uint32_t tempData; + if (spi_flash_read(address + currentOffset, &tempData, 4) != SPI_FLASH_RESULT_OK) { + return false; + } + memcpy((uint8_t *)data + currentOffset, &tempData, size - currentOffset); + } + + return true; +} + +bool EspClass::flashRead(uint32_t address, uint32_t *data, size_t size) { + if ((uintptr_t)data % 4 != 0 || size % 4 != 0) { + return false; + } + return (spi_flash_read(address, data, size) == SPI_FLASH_RESULT_OK); } String EspClass::getSketchMD5() diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index c321db382..54f8d2175 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -22,6 +22,7 @@ #define ESP_H #include +#include "core_esp8266_features.h" #include "spi_vendors.h" /** @@ -149,8 +150,48 @@ class EspClass { bool checkFlashCRC(); bool flashEraseSector(uint32_t sector); - bool flashWrite(uint32_t offset, uint32_t *data, size_t size); - bool flashRead(uint32_t offset, uint32_t *data, size_t size); + /** + * @brief Write @a size bytes from @a data to flash at @a address + * This overload requires @a data and @a size to be always 4 byte aligned and + * @a address to be 4 byte aligned if the write crossess page boundary, + * but guarantees no overhead (except on PUYA flashes) + * @param address address on flash where write should start, 4 byte alignment is conditional + * @param data input buffer, must be 4-byte aligned + * @param size amount of data, must be a multiple of 4 + * @return bool result of operation + * @retval true success + * @retval false failure to write to flash or incorrect alignment of params + */ + bool flashWrite(uint32_t address, const uint32_t *data, size_t size); + /** + * @brief Write @a size bytes from @a data to flash at @a address + * This overload handles all misalignment cases + * @param address address on flash where write should start + * @param data input buffer, passing unaligned memory will cause significant stack usage + * @param size amount of data, passing not multiple of 4 will cause additional reads and writes + * @return bool result of operation + */ + bool flashWrite(uint32_t address, const uint8_t *data, size_t size); + /** + * @brief Read @a size bytes to @a data to flash at @a address + * This overload requires @a data and @a size to be 4 byte aligned + * @param address address on flash where read should start + * @param data input buffer, must be 4-byte aligned + * @param size amount of data, must be a multiple of 4 + * @return bool result of operation + * @retval true success + * @retval false failure to read from flash or incorrect alignment of params + */ + bool flashRead(uint32_t address, uint32_t *data, size_t size); + /** + * @brief Read @a size bytes to @a data to flash at @a address + * This overload handles all misalignment cases + * @param address address on flash where read should start + * @param data input buffer, passing unaligned memory will cause significant stack usage + * @param size amount of data, passing not multiple of 4 will cause additional read + * @return bool result of operation + */ + bool flashRead(uint32_t address, uint8_t *data, size_t size); uint32_t getSketchSize(); String getSketchMD5(); @@ -174,6 +215,40 @@ class EspClass { #else uint32_t getCycleCount(); #endif // !defined(CORE_MOCK) + private: + /** + * @brief Replaces @a byteCount bytes of a 4 byte block on flash + * + * @param address flash address + * @param value buffer with data + * @param byteCount number of bytes to replace + * @return bool result of operation + * @retval true success + * @retval false failed to read/write or invalid args + */ + bool flashReplaceBlock(uint32_t address, const uint8_t *value, uint32_t byteCount); + /** + * @brief Write up to @a size bytes from @a data to flash at @a address + * This function takes case of unaligned memory acces by copying @a data to a temporary buffer, + * it also takes care of page boundary crossing see @a flashWritePageBreak as to why it's done. + * Less than @a size bytes may be written, due to 4 byte alignment requirement of spi_flash_write + * @param address address on flash where write should start + * @param data input buffer + * @param size amount of data + * @return size_t amount of data written, 0 on failure + */ + size_t flashWriteUnalignedMemory(uint32_t address, const uint8_t *data, size_t size); + /** + * @brief Splits up to 4 bytes into 4 byte blocks and writes them to flash + * We need this since spi_flash_write cannot handle writing over a page boundary with unaligned offset + * i.e. spi_flash_write(254, data, 4) will fail, also we cannot write less bytes as in + * spi_flash_write(254, data, 2) since it will be extended internally to 4 bytes and fail + * @param address start of write + * @param data data to be written + * @param size amount of data, must be < 4 + * @return bool result of operation + */ + bool flashWritePageBreak(uint32_t address, const uint8_t *data, size_t size); }; extern EspClass ESP; diff --git a/cores/esp8266/Print.h b/cores/esp8266/Print.h index e49332b31..551755399 100644 --- a/cores/esp8266/Print.h +++ b/cores/esp8266/Print.h @@ -35,17 +35,15 @@ class Print { private: - int write_error; + int write_error = 0; template size_t printNumber(T n, uint8_t base); template inline size_t _println(T v, P... args); -protected: + protected: void setWriteError(int err = 1) { write_error = err; } public: - Print() : - write_error(0) { - } + Print() {} int getWriteError() { return write_error; diff --git a/cores/esp8266/Stream.h b/cores/esp8266/Stream.h index fa786dddc..6dcb508d2 100644 --- a/cores/esp8266/Stream.h +++ b/cores/esp8266/Stream.h @@ -37,7 +37,7 @@ class Stream: public Print { protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _timeout = 1000; // number of milliseconds to wait for the next char before aborting timed read unsigned long _startMillis; // used for timeout measurement int timedRead(); // private method to read stream with timeout int timedPeek(); // private method to peek stream with timeout @@ -48,9 +48,7 @@ class Stream: public Print { virtual int read() = 0; virtual int peek() = 0; - Stream() { - _timeout = 1000; - } + Stream() {} // parsing methods diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index 93149033c..b2e92978e 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -27,18 +27,6 @@ extern "C" uint32_t _FS_start; extern "C" uint32_t _FS_end; UpdaterClass::UpdaterClass() -: _async(false) -, _error(0) -, _buffer(0) -, _bufferLen(0) -, _size(0) -, _startAddress(0) -, _currentAddress(0) -, _command(U_FLASH) -, _ledPin(-1) -, _hash(nullptr) -, _verify(nullptr) -, _progress_callback(nullptr) { #if ARDUINO_SIGNING installSignature(&esp8266::updaterSigningHash, &esp8266::updaterSigningVerifier); @@ -248,7 +236,7 @@ bool UpdaterClass::end(bool evenIfRemaining){ DEBUG_UPDATER.printf_P(PSTR("[Updater] Adjusted binsize: %d\n"), binSize); #endif // Calculate the MD5 and hash using proper size - uint8_t buff[128]; + uint8_t buff[128] __attribute__((aligned(4))); for(int i = 0; i < binSize; i += sizeof(buff)) { ESP.flashRead(_startAddress + i, (uint32_t *)buff, sizeof(buff)); size_t read = std::min((int)sizeof(buff), binSize - i); @@ -267,7 +255,7 @@ bool UpdaterClass::end(bool evenIfRemaining){ _reset(); return false; } - ESP.flashRead(_startAddress + binSize, (uint32_t *)sig, sigLen); + ESP.flashRead(_startAddress + binSize, sig, sigLen); #ifdef DEBUG_UPDATER DEBUG_UPDATER.printf_P(PSTR("[Updater] Received Signature:")); for (size_t i=0; i #include -#include #include #include diff --git a/cores/esp8266/core_esp8266_features.h b/cores/esp8266/core_esp8266_features.h index cc4cd3977..5dea897bc 100644 --- a/cores/esp8266/core_esp8266_features.h +++ b/cores/esp8266/core_esp8266_features.h @@ -54,6 +54,7 @@ // level 0 will enable ALL interrupts, // #ifndef CORE_MOCK + #define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state) :: "memory"); state;})) #define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory") @@ -73,6 +74,9 @@ inline uint32_t esp_get_program_counter() { #else // CORE_MOCK +#define xt_rsil(level) (level) +#define xt_wsr_ps(state) do { (void)(state); } while (0) + inline uint32_t esp_get_program_counter() { return 0; } #endif // CORE_MOCK diff --git a/cores/esp8266/esp8266_peri.h b/cores/esp8266/esp8266_peri.h index 1445b22db..6ed20dfff 100644 --- a/cores/esp8266/esp8266_peri.h +++ b/cores/esp8266/esp8266_peri.h @@ -21,6 +21,9 @@ #ifndef ESP8266_PERI_H_INCLUDED #define ESP8266_PERI_H_INCLUDED +// we expect mocking framework to provide these +#ifndef CORE_MOCK + #include "c_types.h" #include "esp8266_undocumented.h" @@ -847,4 +850,6 @@ extern volatile uint32_t* const esp8266_gpioToFn[16]; **/ #define RANDOM_REG32 ESP8266_DREG(0x20E44) +#endif // ifndef CORE_MOCK + #endif diff --git a/cores/esp8266/flash_hal.cpp b/cores/esp8266/flash_hal.cpp index 4602f8309..986d3745d 100644 --- a/cores/esp8266/flash_hal.cpp +++ b/cores/esp8266/flash_hal.cpp @@ -28,141 +28,27 @@ extern "C" { #include "c_types.h" #include "spi_flash.h" } -/* - spi_flash_read function requires flash address to be aligned on word boundary. - We take care of this by reading first and last words separately and memcpy - relevant bytes into result buffer. - -alignment: 012301230123012301230123 -bytes requested: -------***********------ -read directly: --------xxxxxxxx-------- -read pre: ----aaaa---------------- -read post: ----------------bbbb---- -alignedBegin: ^ -alignedEnd: ^ -*/ int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { optimistic_yield(10000); - uint32_t result = FLASH_HAL_OK; - uint32_t alignedBegin = (addr + 3) & (~3); - uint32_t alignedEnd = (addr + size) & (~3); - if (alignedEnd < alignedBegin) { - alignedEnd = alignedBegin; + // We use flashRead overload that handles proper alignment + if (ESP.flashRead(addr, dst, size)) { + return FLASH_HAL_OK; + } else { + return FLASH_HAL_READ_ERROR; } - - if (addr < alignedBegin) { - uint32_t nb = alignedBegin - addr; - uint32_t tmp; - if (!ESP.flashRead(alignedBegin - 4, &tmp, 4)) { - DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_READ_ERROR; - } - memcpy(dst, ((uint8_t*) &tmp) + 4 - nb, nb); - } - - if (alignedEnd != alignedBegin) { - if (!ESP.flashRead(alignedBegin, (uint32_t*) (dst + alignedBegin - addr), - alignedEnd - alignedBegin)) { - DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_READ_ERROR; - } - } - - if (addr + size > alignedEnd) { - uint32_t nb = addr + size - alignedEnd; - uint32_t tmp; - if (!ESP.flashRead(alignedEnd, &tmp, 4)) { - DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_READ_ERROR; - } - - memcpy(dst + size - nb, &tmp, nb); - } - - return result; } -/* - Like spi_flash_read, spi_flash_write has a requirement for flash address to be - aligned. However it also requires RAM address to be aligned as it reads data - in 32-bit words. Flash address (mis-)alignment is handled much the same way - as for reads, but for RAM alignment we have to copy data into a temporary - buffer. The size of this buffer is a tradeoff between number of writes required - and amount of stack required. This is chosen to be 512 bytes here, but might - be adjusted in the future if there are good reasons to do so. -*/ - -static const int UNALIGNED_WRITE_BUFFER_SIZE = 512; - int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src) { optimistic_yield(10000); - uint32_t alignedBegin = (addr + 3) & (~3); - uint32_t alignedEnd = (addr + size) & (~3); - if (alignedEnd < alignedBegin) { - alignedEnd = alignedBegin; + // We use flashWrite overload that handles proper alignment + if (ESP.flashWrite(addr, src, size)) { + return FLASH_HAL_OK; + } else { + return FLASH_HAL_WRITE_ERROR; } - - if (addr < alignedBegin) { - uint32_t ofs = alignedBegin - addr; - uint32_t nb = (size < ofs) ? size : ofs; - uint8_t tmp[4] __attribute__((aligned(4))) = {0xff, 0xff, 0xff, 0xff}; - memcpy(tmp + 4 - ofs, src, nb); - if (!ESP.flashWrite(alignedBegin - 4, (uint32_t*) tmp, 4)) { - DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_WRITE_ERROR; - } - } - - if (alignedEnd != alignedBegin) { - uint32_t* srcLeftover = (uint32_t*) (src + alignedBegin - addr); - uint32_t srcAlign = ((uint32_t) srcLeftover) & 3; - if (!srcAlign) { - if (!ESP.flashWrite(alignedBegin, (uint32_t*) srcLeftover, - alignedEnd - alignedBegin)) { - DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_WRITE_ERROR; - } - } - else { - uint8_t buf[UNALIGNED_WRITE_BUFFER_SIZE]; - for (uint32_t sizeLeft = alignedEnd - alignedBegin; sizeLeft; ) { - size_t willCopy = std::min(sizeLeft, sizeof(buf)); - memcpy(buf, srcLeftover, willCopy); - - if (!ESP.flashWrite(alignedBegin, (uint32_t*) buf, willCopy)) { - DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_WRITE_ERROR; - } - - sizeLeft -= willCopy; - srcLeftover += willCopy; - alignedBegin += willCopy; - } - } - } - - if (addr + size > alignedEnd) { - uint32_t nb = addr + size - alignedEnd; - uint32_t tmp = 0xffffffff; - memcpy(&tmp, src + size - nb, nb); - - if (!ESP.flashWrite(alignedEnd, &tmp, 4)) { - DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", - __LINE__, addr, size, alignedBegin, alignedEnd); - return FLASH_HAL_WRITE_ERROR; - } - } - - return FLASH_HAL_OK; } int32_t flash_hal_erase(uint32_t addr, uint32_t size) { diff --git a/cores/esp8266/libc_replacements.cpp b/cores/esp8266/libc_replacements.cpp index 0ccf5e04b..f9aa13d55 100644 --- a/cores/esp8266/libc_replacements.cpp +++ b/cores/esp8266/libc_replacements.cpp @@ -127,6 +127,7 @@ void _exit(int status) { abort(); } +int atexit(void (*func)()) __attribute__((weak)); int atexit(void (*func)()) { (void) func; return 0; diff --git a/cores/esp8266/time.cpp b/cores/esp8266/time.cpp index 0ee24278e..a4656d811 100644 --- a/cores/esp8266/time.cpp +++ b/cores/esp8266/time.cpp @@ -127,6 +127,8 @@ int _gettimeofday_r(struct _reent* unused, struct timeval *tp, void *tzp) void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) { + sntp_stop(); + // There is no way to tell when DST starts or stop with this API // So DST is always integrated in TZ // The other API should be preferred @@ -178,6 +180,8 @@ void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, c setServer(0, server1); setServer(1, server2); setServer(2, server3); + + sntp_init(); } void setTZ(const char* tz){ diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfg.h b/cores/esp8266/umm_malloc/umm_malloc_cfg.h index d6b7c5987..2db244475 100644 --- a/cores/esp8266/umm_malloc/umm_malloc_cfg.h +++ b/cores/esp8266/umm_malloc/umm_malloc_cfg.h @@ -17,9 +17,10 @@ #include #include #include -#include + #include -#include +#include "../debug.h" +#include "../esp8266_undocumented.h" #ifdef __cplusplus extern "C" { diff --git a/doc/esp8266wifi/readme.rst b/doc/esp8266wifi/readme.rst index f51b7f495..2c22ee150 100644 --- a/doc/esp8266wifi/readme.rst +++ b/doc/esp8266wifi/readme.rst @@ -156,6 +156,39 @@ The Client class creates `clients `__ +WiFi Multi +~~~~~~~~~~ + +`ESP8266WiFiMulti.h` can be used to connect to a WiFi network with strongest WiFi signal (RSSI). This requires registering one or more access points with SSID and password. It automatically switches to another WiFi network when the WiFi connection is lost. + +Example: + +.. code:: cpp + #include + + ESP8266WiFiMulti wifiMulti; + + // WiFi connect timeout per AP. Increase when connecting takes longer. + const uint32_t connectTimeoutMs = 5000; + + void setup() + { + // Set in station mode + WiFi.mode(WIFI_STA); + + // Register multi WiFi networks + wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); + wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); + wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); + } + + void loop() + { + // Maintain WiFi connection + if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) { + ... + } + } BearSSL Client Secure and Server Secure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -227,8 +260,9 @@ This function returns following codes to describe what is going on with Wi-Fi co * 0 : ``WL_IDLE_STATUS`` when Wi-Fi is in process of changing between statuses * 1 : ``WL_NO_SSID_AVAIL``\ in case configured SSID cannot be reached * 3 : ``WL_CONNECTED`` after successful connection is established -* 4 : ``WL_CONNECT_FAILED`` if password is incorrect -* 6 : ``WL_DISCONNECTED`` if module is not configured in station mode +* 4 : ``WL_CONNECT_FAILED`` if connection failed +* 6 : ``WL_CONNECT_WRONG_PASSWORD`` if password is incorrect +* 7 : ``WL_DISCONNECTED`` if module is not configured in station mode It is a good practice to display and check information returned by functions. Application development and troubleshooting will be easier with that. diff --git a/doc/esp8266wifi/station-class.rst b/doc/esp8266wifi/station-class.rst index 01dab377f..787de4968 100644 --- a/doc/esp8266wifi/station-class.rst +++ b/doc/esp8266wifi/station-class.rst @@ -250,8 +250,9 @@ Wait until module connects to the access point. This function is intended for mo Function returns one of the following connection statuses: - ``WL_CONNECTED`` after successful connection is established -- ``WL_NO_SSID_AVAIL`` in case configured SSID cannot be reached -- ``WL_CONNECT_FAILED`` if password is incorrect +- ``WL_NO_SSID_AVAIL`` in case configured SSID cannot be reached +- ``WL_CONNECT_FAILED`` if connection failed +- ``WL_CONNECT_WRONG_PASSWORD`` if password is incorrect - ``WL_IDLE_STATUS`` when Wi-Fi is in process of changing between statuses - ``WL_DISCONNECTED`` if module is not configured in station mode - ``-1`` on timeout diff --git a/doc/ota_updates/readme.rst b/doc/ota_updates/readme.rst index 6714d3096..12238c54c 100755 --- a/doc/ota_updates/readme.rst +++ b/doc/ota_updates/readme.rst @@ -571,15 +571,16 @@ Example header data: :: - [HTTP_USER_AGENT] => ESP8266-http-Update - [HTTP_X_ESP8266_STA_MAC] => 18:FE:AA:AA:AA:AA - [HTTP_X_ESP8266_AP_MAC] => 1A:FE:AA:AA:AA:AA - [HTTP_X_ESP8266_FREE_SPACE] => 671744 - [HTTP_X_ESP8266_SKETCH_SIZE] => 373940 - [HTTP_X_ESP8266_SKETCH_MD5] => a56f8ef78a0bebd812f62067daf1408a - [HTTP_X_ESP8266_CHIP_SIZE] => 4194304 - [HTTP_X_ESP8266_SDK_VERSION] => 1.3.0 - [HTTP_X_ESP8266_VERSION] => DOOR-7-g14f53a19 + [User-Agent] => ESP8266-http-Update + [x-ESP8266-STA-MAC] => 18:FE:AA:AA:AA:AA + [x-ESP8266-AP-MAC] => 1A:FE:AA:AA:AA:AA + [x-ESP8266-free-space] => 671744 + [x-ESP8266-sketch-size] => 373940 + [x-ESP8266-sketch-md5] => a56f8ef78a0bebd812f62067daf1408a + [x-ESP8266-chip-size] => 4194304 + [x-ESP8266-sdk-version] => 1.3.0 + [x-ESP8266-version] => DOOR-7-g14f53a19 + [x-ESP8266-mode] => sketch With this information the script now can check if an update is needed. It is also possible to deliver different binaries based on the MAC address, as in the following example: @@ -608,20 +609,20 @@ With this information the script now can check if an update is needed. It is als readfile($path); } - if(!check_header('HTTP_USER_AGENT', 'ESP8266-http-Update')) { + if(!check_header('User-Agent', 'ESP8266-http-Update')) { header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403); echo "only for ESP8266 updater!\n"; exit(); } if( - !check_header('HTTP_X_ESP8266_STA_MAC') || - !check_header('HTTP_X_ESP8266_AP_MAC') || - !check_header('HTTP_X_ESP8266_FREE_SPACE') || - !check_header('HTTP_X_ESP8266_SKETCH_SIZE') || - !check_header('HTTP_X_ESP8266_SKETCH_MD5') || - !check_header('HTTP_X_ESP8266_CHIP_SIZE') || - !check_header('HTTP_X_ESP8266_SDK_VERSION') + !check_header('x-ESP8266-STA-MAC') || + !check_header('x-ESP8266-AP-MAC') || + !check_header('x-ESP8266-free-space') || + !check_header('x-ESP8266-sketch-size') || + !check_header('x-ESP8266-sketch-md5') || + !check_header('x-ESP8266-chip-size') || + !check_header('x-ESP8266-sdk-version') ) { header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403); echo "only for ESP8266 updater! (header)\n"; @@ -633,17 +634,17 @@ With this information the script now can check if an update is needed. It is als "18:FE:AA:AA:AA:BB" => "TEMP-1.0.0" ); - if(!isset($db[$_SERVER['HTTP_X_ESP8266_STA_MAC']])) { + if(!isset($db[$_SERVER['x-ESP8266-STA-MAC']])) { header($_SERVER["SERVER_PROTOCOL"].' 500 ESP MAC not configured for updates', true, 500); } - $localBinary = "./bin/".$db[$_SERVER['HTTP_X_ESP8266_STA_MAC']].".bin"; + $localBinary = "./bin/".$db[$_SERVER['x-ESP8266-STA-MAC']].".bin"; // Check if version has been set and does not match, if not, check if // MD5 hash between local binary and ESP8266 binary do not match if not. // then no update has been found. - if((!check_header('HTTP_X_ESP8266_SDK_VERSION') && $db[$_SERVER['HTTP_X_ESP8266_STA_MAC']] != $_SERVER['HTTP_X_ESP8266_VERSION']) - || $_SERVER["HTTP_X_ESP8266_SKETCH_MD5"] != md5_file($localBinary)) { + if((!check_header('x-ESP8266-sdk-version') && $db[$_SERVER['x-ESP8266-STA-MAC']] != $_SERVER['x-ESP8266-version']) + || $_SERVER["x-ESP8266-sketch-md5"] != md5_file($localBinary)) { sendFile($localBinary); } else { header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified', true, 304); diff --git a/libraries/EEPROM/EEPROM.cpp b/libraries/EEPROM/EEPROM.cpp index 90bbf8ca5..0ea72ceca 100644 --- a/libraries/EEPROM/EEPROM.cpp +++ b/libraries/EEPROM/EEPROM.cpp @@ -35,17 +35,11 @@ extern "C" uint32_t _EEPROM_start; EEPROMClass::EEPROMClass(uint32_t sector) : _sector(sector) -, _data(0) -, _size(0) -, _dirty(false) { } EEPROMClass::EEPROMClass(void) : _sector((((uint32_t)&_EEPROM_start - 0x40200000) / SPI_FLASH_SEC_SIZE)) -, _data(0) -, _size(0) -, _dirty(false) { } diff --git a/libraries/EEPROM/EEPROM.h b/libraries/EEPROM/EEPROM.h index 54a9c1e33..e1d804425 100644 --- a/libraries/EEPROM/EEPROM.h +++ b/libraries/EEPROM/EEPROM.h @@ -68,9 +68,9 @@ public: protected: uint32_t _sector; - uint8_t* _data; - size_t _size; - bool _dirty; + uint8_t* _data = nullptr; + size_t _size = 0; + bool _dirty = false; }; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index 93121ffc8..2f9ff1114 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -47,12 +47,10 @@ extern "C" { #include "include/UdpContext.h" //#define DEBUG_SSDP Serial -#define SSDP_INTERVAL 1200 #define SSDP_PORT 1900 #define SSDP_METHOD_SIZE 10 #define SSDP_URI_SIZE 2 #define SSDP_BUFFER_SIZE 64 -#define SSDP_MULTICAST_TTL 2 // ssdp ipv6 is FF05::C // lwip-v2's igmp_joingroup only supports IPv4 @@ -125,19 +123,8 @@ struct SSDPTimer { ETSTimer timer; }; -SSDPClass::SSDPClass() : - _server(0), - _timer(0), - _port(80), - _ttl(SSDP_MULTICAST_TTL), - _interval(SSDP_INTERVAL), - _respondToAddr(0,0,0,0), - _respondToPort(0), - _pending(false), - _st_is_uuid(false), - _delay(0), - _process_time(0), - _notify_time(0) +SSDPClass::SSDPClass() +: _respondToAddr(0,0,0,0) { _uuid[0] = '\0'; _modelNumber[0] = '\0'; diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index 527822f6d..0b310c08e 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -46,6 +46,9 @@ class UdpContext; #define SSDP_MODEL_VERSION_SIZE 32 #define SSDP_MANUFACTURER_SIZE 64 #define SSDP_MANUFACTURER_URL_SIZE 128 +#define SSDP_INTERVAL_SECONDS 1200 +#define SSDP_MULTICAST_TTL 2 +#define SSDP_HTTP_PORT 80 typedef enum { NONE, @@ -101,20 +104,20 @@ class SSDPClass{ void _stopTimer(); static void _onTimerStatic(SSDPClass* self); - UdpContext* _server; - SSDPTimer* _timer; - uint16_t _port; - uint8_t _ttl; - uint32_t _interval; + UdpContext* _server = nullptr; + SSDPTimer* _timer = nullptr; + uint16_t _port = SSDP_HTTP_PORT; + uint8_t _ttl = SSDP_MULTICAST_TTL; + uint32_t _interval = SSDP_INTERVAL_SECONDS; IPAddress _respondToAddr; - uint16_t _respondToPort; + uint16_t _respondToPort = 0; - bool _pending; - bool _st_is_uuid; - unsigned short _delay; - unsigned long _process_time; - unsigned long _notify_time; + bool _pending = false; + bool _st_is_uuid = false; + unsigned short _delay = 0; + unsigned long _process_time = 0; + unsigned long _notify_time = 0; char _schemaURL[SSDP_SCHEMA_URL_SIZE]; char _uuid[SSDP_UUID_SIZE]; diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index bc094b1b6..eed9cb945 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -39,47 +39,12 @@ namespace esp8266webserver { template ESP8266WebServerTemplate::ESP8266WebServerTemplate(IPAddress addr, int port) : _server(addr, port) -, _currentMethod(HTTP_ANY) -, _currentVersion(0) -, _currentStatus(HC_NONE) -, _statusChange(0) -, _keepAlive(false) -, _currentHandler(nullptr) -, _firstHandler(nullptr) -, _lastHandler(nullptr) -, _currentArgCount(0) -, _currentArgs(nullptr) -, _currentArgsHavePlain(0) -, _postArgsLen(0) -, _postArgs(nullptr) -, _headerKeysCount(0) -, _currentHeaders(nullptr) -, _contentLength(0) -, _chunked(false) -, _corsEnabled(false) { } template ESP8266WebServerTemplate::ESP8266WebServerTemplate(int port) : _server(port) -, _currentMethod(HTTP_ANY) -, _currentVersion(0) -, _currentStatus(HC_NONE) -, _statusChange(0) -, _currentHandler(nullptr) -, _firstHandler(nullptr) -, _lastHandler(nullptr) -, _currentArgCount(0) -, _currentArgs(nullptr) -, _currentArgsHavePlain(0) -, _postArgsLen(0) -, _postArgs(nullptr) -, _headerKeysCount(0) -, _currentHeaders(nullptr) -, _contentLength(0) -, _chunked(false) -, _corsEnabled(false) { } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 3c08f72a3..23b5b328a 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -263,35 +263,35 @@ protected: ServerType _server; ClientType _currentClient; - HTTPMethod _currentMethod; + HTTPMethod _currentMethod = HTTP_ANY; String _currentUri; - uint8_t _currentVersion; - HTTPClientStatus _currentStatus; - unsigned long _statusChange; - bool _keepAlive; + uint8_t _currentVersion = 0; + HTTPClientStatus _currentStatus = HC_NONE; + unsigned long _statusChange = 0; - RequestHandlerType* _currentHandler; - RequestHandlerType* _firstHandler; - RequestHandlerType* _lastHandler; + RequestHandlerType* _currentHandler = nullptr; + RequestHandlerType* _firstHandler = nullptr; + RequestHandlerType* _lastHandler = nullptr; THandlerFunction _notFoundHandler; THandlerFunction _fileUploadHandler; - int _currentArgCount; - RequestArgument* _currentArgs; - int _currentArgsHavePlain; + int _currentArgCount = 0; + RequestArgument* _currentArgs = nullptr; + int _currentArgsHavePlain = 0; std::unique_ptr _currentUpload; - int _postArgsLen; - RequestArgument* _postArgs; + int _postArgsLen = 0; + RequestArgument* _postArgs = nullptr; - int _headerKeysCount; - RequestArgument* _currentHeaders; + int _headerKeysCount = 0; + RequestArgument* _currentHeaders = nullptr; - size_t _contentLength; + size_t _contentLength = 0; String _responseHeaders; String _hostHeader; - bool _chunked; - bool _corsEnabled; + bool _chunked = false; + bool _corsEnabled = false; + bool _keepAlive = false; String _snonce; // Store noance and opaque for future comparison String _sopaque; diff --git a/libraries/ESP8266WiFi/src/CertStoreBearSSL.cpp b/libraries/ESP8266WiFi/src/CertStoreBearSSL.cpp index 9f3e0ac80..faa34e7a3 100644 --- a/libraries/ESP8266WiFi/src/CertStoreBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/CertStoreBearSSL.cpp @@ -21,7 +21,7 @@ #include -#ifdef DEBUG_ESP_SSL +#if defined(DEBUG_ESP_SSL) && defined(DEBUG_ESP_PORT) #define DEBUG_BSSL(fmt, ...) DEBUG_ESP_PORT.printf_P((PGM_P)PSTR( "BSSL:" fmt), ## __VA_ARGS__) #else #define DEBUG_BSSL(...) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index 304883506..1df25be3e 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -827,15 +827,21 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state) } } // state->state.fwconfig.bssid is not real bssid (it's what user may have provided when bssid_set==1) - if (WiFi.begin((const char*)state->state.fwconfig.ssid, + auto beginResult = WiFi.begin((const char*)state->state.fwconfig.ssid, (const char*)state->state.fwconfig.password, state->state.channel, nullptr/*(const uint8_t*)state->state.fwconfig.bssid*/, // <- try with gw's mac address? - true) == WL_CONNECT_FAILED) + true); + if (beginResult == WL_CONNECT_FAILED) { DEBUG_WIFI("core: resume: WiFi.begin failed\n"); return false; } + if (beginResult == WL_WRONG_PASSWORD) + { + DEBUG_WIFI("core: resume: WiFi.begin wrong password\n"); + return false; + } } if (state->state.mode & WIFI_AP) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 63ca5ca41..f41699d01 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -60,6 +60,9 @@ static void printWiFiStatus(wl_status_t status) case WL_CONNECT_FAILED: DEBUG_WIFI_MULTI("[WIFIM] Connecting failed.\n"); break; + case WL_WRONG_PASSWORD: + DEBUG_WIFI_MULTI("[WIFIM] Wrong password.\n"); + break; default: DEBUG_WIFI_MULTI("[WIFIM] Connecting failed (%d).\n", status); break; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 5082dfd88..65f0ea35a 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -624,8 +624,9 @@ wl_status_t ESP8266WiFiSTAClass::status() { case STATION_NO_AP_FOUND: return WL_NO_SSID_AVAIL; case STATION_CONNECT_FAIL: - case STATION_WRONG_PASSWORD: return WL_CONNECT_FAILED; + case STATION_WRONG_PASSWORD: + return WL_WRONG_PASSWORD; case STATION_IDLE: return WL_IDLE_STATUS; default: diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index d482b9cd6..a38909cc0 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -59,7 +59,7 @@ extern "C" { #endif -#ifdef DEBUG_ESP_SSL +#if defined(DEBUG_ESP_SSL) && defined(DEBUG_ESP_PORT) #define DEBUG_BSSL(fmt, ...) DEBUG_ESP_PORT.printf_P((PGM_P)PSTR( "BSSL:" fmt), ## __VA_ARGS__) #else #define DEBUG_BSSL(...) @@ -664,7 +664,7 @@ extern "C" { if (!xc->done_cert) { br_sha1_update(&xc->sha1_cert, buf, len); br_x509_decoder_push(&xc->ctx, (const void*)buf, len); -#ifdef DEBUG_ESP_SSL +#if defined(DEBUG_ESP_SSL) && defined(DEBUG_ESP_PORT) DEBUG_BSSL("CERT: "); for (size_t i=0; i // LwipIntf::stateUpCB() +#include "lwip/igmp.h" namespace esp8266 { @@ -61,13 +62,7 @@ MDNSResponder::MDNSResponder(void) m_pUDPContext(0), m_pcHostname(0), m_pServiceQueries(0), - m_fnServiceTxtCallback(0), -#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - m_bPassivModeEnabled(true), -#else - m_bPassivModeEnabled(false), -#endif - m_netif(nullptr) + m_fnServiceTxtCallback(0) { } @@ -93,104 +88,29 @@ MDNSResponder::~MDNSResponder(void) Finally the responder is (re)started */ -bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL) +bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& /*p_IPAddress*/, uint32_t /*p_u32TTL*/) { - - (void)p_u32TTL; // ignored bool bResult = false; - if (0 == m_pUDPContext) + if (_setHostname(p_pcHostname)) { - if (_setHostname(p_pcHostname)) - { - - //// select interface - - m_netif = nullptr; - IPAddress ipAddress = p_IPAddress; - - if (!ipAddress.isSet()) - { - - IPAddress sta = WiFi.localIP(); - IPAddress ap = WiFi.softAPIP(); - - if (sta.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] STA interface selected\n"))); - ipAddress = sta; - } - else if (ap.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] AP interface selected\n"))); - ipAddress = ap; - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] standard interfaces are not up, please specify one in ::begin()\n"))); - return false; - } - - // continue to ensure interface is UP - } - - // check existence of this IP address in the interface list - bool found = false; - m_netif = nullptr; - for (auto a : addrList) - if (ipAddress == a.addr()) - { - if (a.ifUp()) - { - found = true; - m_netif = a.interface(); - break; - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str());); - } - if (!found) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str());); - return false; - } - - //// done selecting the interface - - if (m_netif->num == STATION_IF) - { - - m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent) - { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); - }); - - m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent) - { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); - }); - } - - bResult = _restart(); - } - DEBUG_EX_ERR(if (!bResult) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); - }); + bResult = _restart(); } - else + + LwipIntf::stateUpCB + ( + [this](netif * intf) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: Ignoring multiple calls to begin (Ignored host domain: '%s')!\n"), (p_pcHostname ? : "-"));); + (void)intf; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] new Interface '%c%c' is UP! restarting\n"), intf->name[0], intf->name[1])); + _restart(); } + ); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); + }); + return bResult; } @@ -207,9 +127,6 @@ bool MDNSResponder::close(void) if (0 != m_pUDPContext) { - m_GotIPHandler.reset(); // reset WiFi event callbacks. - m_DisconnectedHandler.reset(); - _announce(false, true); _resetProbeStatus(false); // Stop probing _releaseServiceQueries(); @@ -1329,11 +1246,6 @@ bool MDNSResponder::notifyAPChange(void) */ bool MDNSResponder::update(void) { - - if (m_bPassivModeEnabled) - { - m_bPassivModeEnabled = false; - } return _process(true); } @@ -1374,6 +1286,94 @@ MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port, return hService; } +/* + + MULTICAST GROUPS + +*/ + +/* + MDNSResponder::_joinMulticastGroups +*/ +bool MDNSResponder::_joinMulticastGroups(void) +{ + bool bResult = false; + + // Join multicast group(s) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + { + if (netif_is_up(pNetIf)) + { +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + if (!(pNetIf->flags & NETIF_FLAG_IGMP)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n"));); + pNetIf->flags |= NETIF_FLAG_IGMP; + + if (ERR_OK != igmp_start(pNetIf)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: igmp_start FAILED!\n"));); + } + } + + if ((ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4)))) + { + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: igmp_joingroup_netif(" NETIFID_STR ": %s) FAILED!\n"), + NETIFID_VAL(pNetIf), IPAddress(multicast_addr_V4).toString().c_str());); + } +#endif + +#ifdef MDNS_IPV6_SUPPORT + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + bResult = ((bResult) && + (ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)))); + DEBUG_EX_ERR_IF(!bResult, DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"), + NETIFID_VAL(pNetIf))); +#endif + } + } + return bResult; +} + +/* + clsLEAmDNS2_Host::_leaveMulticastGroups +*/ +bool MDNSResponder::_leaveMulticastGroups() +{ + bool bResult = false; + + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + { + if (netif_is_up(pNetIf)) + { + bResult = true; + + // Leave multicast group(s) +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + if (ERR_OK != mld6_leavegroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } +#endif + } + } + return bResult; +} + + } //namespace MDNSImplementation diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h index 6037f0d13..091bebaea 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -164,6 +164,10 @@ namespace MDNSImplementation */ #define MDNS_QUERYSERVICES_WAIT_TIME 1000 +/* + Timeout for udpContext->sendtimeout() +*/ +#define MDNS_UDPCONTEXT_TIMEOUT 50 /** MDNSResponder @@ -185,6 +189,8 @@ public: { return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL); } + bool _joinMulticastGroups(void); + bool _leaveMulticastGroups(void); // Finish MDNS processing bool close(void); @@ -1184,6 +1190,7 @@ protected: ~stcMDNSSendParameter(void); bool clear(void); + bool clearCachedNames(void); bool shiftOffset(uint16_t p_u16Shift); @@ -1199,12 +1206,8 @@ protected: UdpContext* m_pUDPContext; char* m_pcHostname; stcMDNSServiceQuery* m_pServiceQueries; - WiFiEventHandler m_DisconnectedHandler; - WiFiEventHandler m_GotIPHandler; MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback; - bool m_bPassivModeEnabled; stcProbeInformation m_HostProbeInformation; - const netif* m_netif; // network interface to run on /** CONTROL **/ /* MAINTENANCE */ @@ -1259,11 +1262,6 @@ protected: uint16_t p_u16QueryType, stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0); - const IPAddress _getResponseMulticastInterface() const - { - return IPAddress(m_netif->ip_addr); - } - uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader, bool* p_pbFullNameMatch = 0) const; uint8_t _replyMaskForService(const stcMDNS_RRHeader& p_RRHeader, diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index f74739ae6..7722ea602 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -33,7 +33,7 @@ #ifdef MDNS_IPV4_SUPPORT #include #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT #include #endif @@ -172,7 +172,7 @@ const char* clsLEAMDNSHost::clsConsts::pcUDP = "udp"; #ifdef MDNS_IPV4_SUPPORT const char* clsLEAMDNSHost::clsConsts::pcReverseIPv4Domain = "in-addr"; #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT const char* clsLEAMDNSHost::clsConsts::pcReverseIPv6Domain = "ip6"; #endif const char* clsLEAMDNSHost::clsConsts::pcReverseTopDomain = "arpa"; @@ -904,7 +904,7 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; bResult = ((bResult) && (ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)))); @@ -937,7 +937,7 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; if (ERR_OK != mld6_leavegroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index ddc5fc1ad..7d0c4c8de 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -110,7 +110,7 @@ #define MDNS_IPV4_SUPPORT #if LWIP_IPV6 -#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) +#define MDNS2_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) #endif namespace esp8266 @@ -136,7 +136,7 @@ protected: #ifdef MDNS_IPV4_SUPPORT static constexpr uint16_t u16IPv4Size = 4; // IPv4 address size in bytes #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT static constexpr uint16_t u16IPv6Size = 16; // IPv6 address size in bytes #endif static constexpr size_t stServiceTxtMaxLength = 1300; // Maximum length for all service txts for one service @@ -168,7 +168,7 @@ protected: #ifdef MDNS_IPV4_SUPPORT static const char* pcReverseIPv4Domain; // "in-addr"; #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT static const char* pcReverseIPv6Domain; // "ip6"; #endif static const char* pcReverseTopDomain; // "arpa"; @@ -246,7 +246,7 @@ protected: #ifdef MDNS_IPV4_SUPPORT V4 = 0x01, #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT V6 = 0x02, #endif }; @@ -784,7 +784,7 @@ protected: bool clear(void); }; -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /** clsRRAnswerAAAA */ @@ -935,7 +935,7 @@ public: #ifdef MDNS_IPV4_SUPPORT IPv4Address = 0x10, // IPv4 address #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT IPv6Address = 0x20, // IPv6 address #endif }; @@ -1004,7 +1004,7 @@ public: #ifdef MDNS_IPV4_SUPPORT clsIPAddressWithTTL::list m_IPv4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT clsIPAddressWithTTL::list m_IPv6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 #endif typeQueryAnswerType m_QueryAnswerFlags; // enuQueryAnswerType @@ -1029,7 +1029,7 @@ public: const clsIPAddressWithTTL* IPv4AddressAtIndex(uint32_t p_u32Index) const; clsIPAddressWithTTL* IPv4AddressAtIndex(uint32_t p_u32Index); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool releaseIPv6Addresses(void); bool addIPv6Address(clsIPAddressWithTTL* p_pIPAddress); bool removeIPv6Address(clsIPAddressWithTTL* p_pIPAddress); @@ -1081,7 +1081,7 @@ public: bool IPv4AddressAvailable(void) const; clsIPAddressVector IPv4Addresses(void) const; #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool IPv6AddressAvailable(void) const; clsIPAddressVector IPv6Addresses(void) const; #endif @@ -1362,7 +1362,7 @@ protected: #ifdef MDNS_IPV4_SUPPORT bool _processAAnswer(const clsRRAnswerA* p_pAAnswer); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool _processAAAAAnswer(const clsRRAnswerAAAA* p_pAAAAAnswer); #endif @@ -1426,7 +1426,7 @@ protected: uint16_t p_u16RDLength); bool _readRRAnswerTXT(clsRRAnswerTXT& p_rRRAnswerTXT, uint16_t p_u16RDLength); -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool _readRRAnswerAAAA(clsRRAnswerAAAA& p_rRRAnswerAAAA, uint16_t p_u16RDLength); #endif @@ -1455,7 +1455,7 @@ protected: bool _buildDomainForReverseIPv4(IPAddress p_IPv4Address, clsRRDomain& p_rReverseIPv4Domain) const; #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool _buildDomainForReverseIPv6(IPAddress p_IPv4Address, clsRRDomain& p_rReverseIPv6Domain) const; #endif @@ -1520,7 +1520,7 @@ protected: clsSendParameter& p_rSendParameter); bool _writeMDNSAnswer_TXT(clsService& p_rService, clsSendParameter& p_rSendParameter); -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, clsSendParameter& p_rSendParameter); bool _writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, @@ -1537,7 +1537,7 @@ protected: bool _writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, clsSendParameter& p_rSendParameter); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool _writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, clsSendParameter& p_rSendParameter); #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index c3b79c02b..4325df7ba 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -218,7 +218,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, (true) #endif && -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT (m_pUDPContext->getRemoteAddress().isV6()) && (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_pUDPContext->getRemoteAddress()))) #else @@ -304,7 +304,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, sendParameter.m_u32HostReplyMask &= ~static_cast(enuContentFlag::PTR_IPv4); } #endif - #ifdef MDNS_IPV6_SUPPORT + #ifdef MDNS2_IPV6_SUPPORT if (u32HostMatchMask & static_cast(enuContentFlag::PTR_IPv6)) { // IPv6 PTR was asked for, but is already known -> skipping @@ -330,7 +330,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, else if (u32HostMatchMask & static_cast(enuContentFlag::AAAA)) { // IPv6 address was asked for - #ifdef MDNS_IPV6_SUPPORT + #ifdef MDNS2_IPV6_SUPPORT if ((enuAnswerType::AAAA == pKnownRRAnswer->answerType()) && (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V6))) { @@ -381,7 +381,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, } } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (enuAnswerType::AAAA == pKnownRRAnswer->answerType()) { IPAddress localIPAddress(_getResponderIPAddress(pNetIf, enuIPProtocolType::V6)); @@ -775,7 +775,7 @@ bool clsLEAMDNSHost::_processAnswers(netif* pNetIf, const clsLEAMDNSHost::clsRRA bResult = _processAAnswer((clsRRAnswerA*)pRRAnswer); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT // AAAA -> IPv6Address else if (enuAnswerType::AAAA == pRRAnswer->answerType()) { @@ -802,7 +802,7 @@ bool clsLEAMDNSHost::_processAnswers(netif* pNetIf, const clsLEAMDNSHost::clsRRA bPossibleEcho = true; } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if ((enuAnswerType::AAAA == pRRAnswer->answerType()) && (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V6))) { @@ -1159,7 +1159,7 @@ bool clsLEAMDNSHost::_processAAnswer(const clsLEAMDNSHost::clsRRAnswerA* p_pAAns } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* clsLEAmDNS2_Host::_processAAAAAnswer (level 3) */ @@ -1298,7 +1298,7 @@ bool clsLEAMDNSHost::_updateProbeStatus() true #endif ) || ( - #ifdef MDNS_IPV6_SUPPORT + #ifdef MDNS2_IPV6_SUPPORT _getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() // OR has IPv6 address #else true @@ -1511,7 +1511,7 @@ bool clsLEAMDNSHost::_sendHostProbe() #ifdef MDNS_IPV4_SUPPORT sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::A); // Add A answer #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::AAAA); // Add AAAA answer #endif } @@ -1705,7 +1705,7 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::A); // A answer sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::PTR_IPv4); // PTR_IPv4 answer #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::AAAA); // AAAA answer sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::PTR_IPv6); // PTR_IPv6 answer #endif @@ -1892,7 +1892,7 @@ bool clsLEAMDNSHost::_checkQueryCache() pQAnswer->releaseIPv4Addresses(); queryAnswerContentFlags |= static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT pQAnswer->releaseIPv6Addresses(); queryAnswerContentFlags |= static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); #endif @@ -1991,7 +1991,7 @@ bool clsLEAMDNSHost::_checkQueryCache() pQAnswer->removeIPv4Address(pIPv4Address); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT // IPv6Address (from AAAA) clsQuery::clsAnswer::clsIPAddressWithTTL::list expiredIPv6Addresses; bool bAAAAUpdateQuerySent = false; @@ -2095,7 +2095,7 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(netif* pNetIf, u32ReplyMask |= static_cast(enuContentFlag::PTR_IPv4); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT clsRRDomain reverseIPv6Domain; if ((_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet()) && (_buildDomainForReverseIPv6(_getResponderIPAddress(pNetIf, enuIPProtocolType::V6), reverseIPv6Domain)) && @@ -2121,7 +2121,7 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(netif* pNetIf, u32ReplyMask |= static_cast(enuContentFlag::A); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if ((DNS_RRTYPE_AAAA == p_RRHeader.m_Attributes.m_u16Type) || (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index 186d913a3..9e584e48d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -141,7 +141,7 @@ bool clsLEAMDNSHost::_printRRAnswer(const clsLEAMDNSHost::clsRRAnswer& p_RRAnswe } break; } -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT case DNS_RRTYPE_AAAA: DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((clsRRAnswerAAAA*&)p_RRAnswer)->m_IPAddress.toString().c_str()); break; @@ -175,7 +175,7 @@ const char* clsLEAMDNSHost::_RRType2Name(uint16_t p_u16RRType) const #endif case DNS_RRTYPE_PTR: strcpy_P(acRRName, PSTR("PTR")); break; case DNS_RRTYPE_TXT: strcpy_P(acRRName, PSTR("TXT")); break; -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT case DNS_RRTYPE_AAAA: strcpy_P(acRRName, PSTR("AAAA")); break; #endif case DNS_RRTYPE_SRV: strcpy_P(acRRName, PSTR("SRV")); break; @@ -288,7 +288,7 @@ const char* clsLEAMDNSHost::_NSECBitmap2String(const clsNSECBitmap* p_pNSECBitma { strcat_P(acFlagsString, PSTR("PTR ")); // 4 } -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (p_pNSECBitmap->getBit(DNS_RRTYPE_AAAA)) { strcat_P(acFlagsString, PSTR("AAAA ")); // 5 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index dcf3c4b76..9c323bc32 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -1898,7 +1898,7 @@ bool clsLEAMDNSHost::clsRRAnswerTXT::clear(void) */ -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* clsLEAMDNSHost::clsRRAnswerAAAA::clsRRAnswerAAAA constructor @@ -2398,7 +2398,7 @@ bool clsLEAMDNSHost::clsQuery::clsAnswer::clear(void) (true) #endif && -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT (releaseIPv6Addresses()) #else (true) @@ -2528,7 +2528,7 @@ const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost:: } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* clsLEAMDNSHost::clsQuery::clsAnswer::releaseIPv6Addresses @@ -2793,7 +2793,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsIPAddressVector clsLEAMDNSHost:: } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6AddressAvailable @@ -2913,7 +2913,7 @@ size_t clsLEAMDNSHost::clsQuery::clsAnswerAccessor::printTo(Print& p_Print) cons } } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (IPv6AddressAvailable()) { stLen += p_Print.print(cpcI); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index f77e0a5e1..0d719da36 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -84,7 +84,7 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: No IPv4 address available!\n"), _DH()); }); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT // Only send out IPv6 messages, if we've got an IPv6 address if (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet()) { @@ -128,7 +128,7 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete bResult = _sendMessage_Multicast(pNetIf, p_rSendParameter, static_cast(enuIPProtocolType::V4)); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (((!ipRemote.isSet()) || // NO remote IP (ipRemote.isV6())) && // OR IPv6 (u8AvailableProtocols & static_cast(enuIPProtocolType::V6))) // AND IPv6 protocol available @@ -182,7 +182,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (p_IPProtocolTypes & static_cast(enuIPProtocolType::V6)) { IPAddress ip6MulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); @@ -308,7 +308,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv4 FAILED!\n"), _DH());); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT // AAAA if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast(enuContentFlag::AAAA)) && @@ -383,7 +383,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam #ifdef MDNS_IPV4_SUPPORT bool bNeedsAdditionalAnswerA = false; #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool bNeedsAdditionalAnswerAAAA = false; #endif for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) @@ -420,7 +420,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam bNeedsAdditionalAnswerA = true; } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if ((bResult) && (!(p_rSendParameter.m_u32HostReplyMask & static_cast(enuContentFlag::AAAA)))) // Add IPv6 address { @@ -455,7 +455,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT // Answer AAAA needed? if ((bResult) && (bNeedsAdditionalAnswerAAAA) && @@ -481,7 +481,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast(enuContentFlag::PTR_IPv4)); u32NSECContent &= ~static_cast(enuContentFlag::PTR_IPv4); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT uint32_t u32NSECContent_PTR_IPv6 = (u32NSECContent & static_cast(enuContentFlag::PTR_IPv6)); u32NSECContent &= ~static_cast(enuContentFlag::PTR_IPv6); #endif @@ -491,7 +491,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam #ifdef MDNS_IPV4_SUPPORT + (u32NSECContent_PTR_IPv4 ? 1 : 0) #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT + (u32NSECContent_PTR_IPv6 ? 1 : 0) #endif )) @@ -504,7 +504,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)).isSet()) || (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter)))) #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT // Write separate answer for host PTR IPv6 && ((!u32NSECContent_PTR_IPv6) || ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet()) || @@ -566,7 +566,7 @@ bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, #ifdef MDNS_IPV4_SUPPORT bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_A); #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_AAAA); #endif break; @@ -623,7 +623,7 @@ IPAddress clsLEAMDNSHost::_getResponderIPAddress(netif* pNetIf, enuIPProtocolTyp ipResponder = netif_ip_addr4(pNetIf); } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (enuIPProtocolType::V6 == p_IPProtocolType) { bool bCheckLinkLocal = true; @@ -731,7 +731,7 @@ bool clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) p_rpRRAnswer = new clsRRAnswerTXT(header, u32TTL); bResult = _readRRAnswerTXT(*(clsRRAnswerTXT*&)p_rpRRAnswer, u16RDLength); break; -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT case DNS_RRTYPE_AAAA: p_rpRRAnswer = new clsRRAnswerAAAA(header, u32TTL); bResult = _readRRAnswerAAAA(*(clsRRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); @@ -779,7 +779,7 @@ bool clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) } break; } -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT case DNS_RRTYPE_AAAA: DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((clsRRAnswerAAAA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); break; @@ -968,7 +968,7 @@ bool clsLEAMDNSHost::_readRRAnswerTXT(clsLEAMDNSHost::clsRRAnswerTXT& p_rRRAnswe return bResult; } -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT bool clsLEAMDNSHost::_readRRAnswerAAAA(clsLEAMDNSHost::clsRRAnswerAAAA& p_rRRAnswerAAAA, uint16_t p_u16RDLength) { @@ -1280,7 +1280,7 @@ bool clsLEAMDNSHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, } #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* MDNSResponder::_buildDomainForReverseIPv6 @@ -2014,7 +2014,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_TXT(clsLEAMDNSHost::clsService& p_rService return bResult; } -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* MDNSResponder::_writeMDNSAnswer_AAAA @@ -2189,7 +2189,7 @@ clsLEAMDNSHost::clsNSECBitmap* clsLEAMDNSHost::_createNSECBitmap(uint32_t p_u32N { pNSECBitmap->setBit(DNS_RRTYPE_PTR); // 12/0x0C } -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT if (p_u32NSECContent & static_cast(enuContentFlag::AAAA)) { pNSECBitmap->setBit(DNS_RRTYPE_AAAA); // 28/0x1C @@ -2335,7 +2335,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, #endif -#ifdef MDNS_IPV6_SUPPORT +#ifdef MDNS2_IPV6_SUPPORT /* MDNSResponder::_writeMDNSAnswer_NSEC_PTR_IPv6(host) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp index 03ade10c7..bc8cb3a69 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -85,10 +85,8 @@ bool MDNSResponder::_process(bool p_bUserContext) } else { - bResult = (m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - _updateProbeStatus() && // Probing - _checkServiceQueryCache(); // Service query cache check + bResult = _updateProbeStatus() && // Probing + _checkServiceQueryCache(); // Service query cache check } return bResult; } @@ -99,13 +97,10 @@ bool MDNSResponder::_process(bool p_bUserContext) bool MDNSResponder::_restart(void) { - return ((m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - (_resetProbeStatus(true)) && // Stop and restart probing + return ((_resetProbeStatus(true)) && // Stop and restart probing (_allocUDPContext())); // Restart UDP } - /** RECEIVING */ @@ -192,8 +187,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea { // Define host replies, BUT only answer queries after probing is done u8HostOrServiceReplies = - sendParameter.m_u8HostReplyMask |= (((m_bPassivModeEnabled) || - (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus)) + sendParameter.m_u8HostReplyMask |= (((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus)) ? _replyMaskForHost(questionRR.m_Header, 0) : 0); DEBUG_EX_INFO(if (u8HostOrServiceReplies) @@ -222,8 +216,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) { // Define service replies, BUT only answer queries after probing is done - uint8_t u8ReplyMaskForQuestion = (((m_bPassivModeEnabled) || - (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus)) + uint8_t u8ReplyMaskForQuestion = (((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus)) ? _replyMaskForService(questionRR.m_Header, *pService, 0) : 0); u8HostOrServiceReplies |= (pService->m_u8ReplyMask |= u8ReplyMaskForQuestion); @@ -364,9 +357,8 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea // IP4 address was asked for #ifdef MDNS_IP4_SUPPORT if ((AnswerType_A == pKnownRRAnswer->answerType()) && - (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface())) + (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == m_pUDPContext->getInputNetif()->ip_addr)) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n"));); sendParameter.m_u8HostReplyMask &= ~ContentFlag_A; } // else: RData NOT IP4 length !! @@ -399,7 +391,8 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea #ifdef MDNS_IP4_SUPPORT if (AnswerType_A == pKnownRRAnswer->answerType()) { - IPAddress localIPAddress(_getResponseMulticastInterface()); + + IPAddress localIPAddress(m_pUDPContext->getInputNetif()->ip_addr); if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) { // SAME IP address -> We've received an old message from ourselfs (same IP) @@ -1221,9 +1214,7 @@ bool MDNSResponder::_updateProbeStatus(void) // // Probe host domain - if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND - //TODO: Fix the following to allow Ethernet shield or other interfaces - (_getResponseMulticastInterface() != IPAddress())) // Has IP address + if (ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n"));); @@ -2007,11 +1998,17 @@ uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader& // PTR request #ifdef MDNS_IP4_SUPPORT stcMDNS_RRDomain reverseIP4Domain; - if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(), reverseIP4Domain)) && - (p_RRHeader.m_Domain == reverseIP4Domain)) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) { - // Reverse domain match - u8ReplyMask |= ContentFlag_PTR_IP4; + if (netif_is_up(pNetIf)) + { + if ((_buildDomainForReverseIP4(pNetIf->ip_addr, reverseIP4Domain)) && + (p_RRHeader.m_Domain == reverseIP4Domain)) + { + // Reverse domain match + u8ReplyMask |= ContentFlag_PTR_IP4; + } + } } #endif #ifdef MDNS_IP6_SUPPORT diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp index 7dc3773de..48f4e4c5e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp @@ -168,31 +168,23 @@ bool MDNSResponder::_allocUDPContext(void) { DEBUG_EX_INFO(DEBUG_OUTPUT.println("[MDNSResponder] _allocUDPContext");); - bool bResult = false; - _releaseUDPContext(); + _joinMulticastGroups(); -#ifdef MDNS_IP4_SUPPORT - ip_addr_t multicast_addr = DNS_MQUERY_IPV4_GROUP_INIT; -#endif -#ifdef MDNS_IP6_SUPPORT - //TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing) - multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT; -#endif - if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) + m_pUDPContext = new UdpContext; + m_pUDPContext->ref(); + + if (m_pUDPContext->listen(IP4_ADDR_ANY, DNS_MQUERY_PORT)) { - m_pUDPContext = new UdpContext; - m_pUDPContext->ref(); - - if (m_pUDPContext->listen(IP4_ADDR_ANY, DNS_MQUERY_PORT)) - { - m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); - m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this)); - - bResult = m_pUDPContext->connect(&multicast_addr, DNS_MQUERY_PORT); - } + m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); + m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this)); } - return bResult; + else + { + return false; + } + + return true; } /* @@ -205,6 +197,7 @@ bool MDNSResponder::_releaseUDPContext(void) { m_pUDPContext->unref(); m_pUDPContext = 0; + _leaveMulticastGroups(); } return true; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp index 8f0d2f7cf..0e128aea8 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp @@ -2408,12 +2408,25 @@ bool MDNSResponder::stcMDNSSendParameter::clear(void) delete m_pQuestions; m_pQuestions = pNext; } + + return clearCachedNames();; +} +/* + MDNSResponder::stcMDNSSendParameter::clear cached names +*/ +bool MDNSResponder::stcMDNSSendParameter::clearCachedNames(void) +{ + + m_u16Offset = 0; + while (m_pDomainCacheItems) { stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext; delete m_pDomainCacheItems; m_pDomainCacheItems = pNext; } + m_pDomainCacheItems = nullptr; + return true; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp index c5858690a..1b8e33789 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp @@ -89,8 +89,8 @@ bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSen }); IPAddress ipRemote; ipRemote = m_pUDPContext->getRemoteAddress(); - bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface())) && - (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort()))); + bResult = ((_prepareMDNSMessage(p_rSendParameter, m_pUDPContext->getInputNetif()->ip_addr)) && + (m_pUDPContext->sendTimeout(ipRemote, m_pUDPContext->getRemotePort(), MDNS_UDPCONTEXT_TIMEOUT))); } else // Multicast response { @@ -121,25 +121,32 @@ bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParamet bool bResult = false; - IPAddress fromIPAddress; - fromIPAddress = _getResponseMulticastInterface(); - m_pUDPContext->setMulticastInterface(fromIPAddress); + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + { + if (netif_is_up(pNetIf)) + { + IPAddress fromIPAddress; + //fromIPAddress = _getResponseMulticastInterface(); + fromIPAddress = pNetIf->ip_addr; + m_pUDPContext->setMulticastInterface(fromIPAddress); #ifdef MDNS_IP4_SUPPORT - IPAddress toMulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); + IPAddress toMulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); #endif #ifdef MDNS_IP6_SUPPORT - //TODO: set multicast address - IPAddress toMulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); + //TODO: set multicast address + IPAddress toMulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); #endif - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str());); - bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) && - (m_pUDPContext->send(toMulticastAddress, DNS_MQUERY_PORT))); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str());); + bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) && + (m_pUDPContext->sendTimeout(toMulticastAddress, DNS_MQUERY_PORT, MDNS_UDPCONTEXT_TIMEOUT))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!\n")); - }); + DEBUG_EX_ERR(if (!bResult) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!\n")); + }); + } + } return bResult; } @@ -157,6 +164,7 @@ bool MDNSResponder::_prepareMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_r { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage\n"));); bool bResult = true; + p_rSendParameter.clearCachedNames(); // Need to remove cached names, p_SendParameter might have been used before on other interface // Prepare header; count answers stcMDNS_MsgHeader msgHeader(p_rSendParameter.m_u16ID, p_rSendParameter.m_bResponse, 0, p_rSendParameter.m_bAuthorative); diff --git a/libraries/esp8266/examples/interactive/interactive.ino b/libraries/esp8266/examples/interactive/interactive.ino index 3c21455a2..b3bd1ff93 100644 --- a/libraries/esp8266/examples/interactive/interactive.ino +++ b/libraries/esp8266/examples/interactive/interactive.ino @@ -42,7 +42,8 @@ void setup() { "WL_CONNECTED = 3\n" "WL_CONNECT_FAILED = 4\n" "WL_CONNECTION_LOST = 5\n" - "WL_DISCONNECTED = 6\n" + "WL_WRONG_PASSWORD = 6\n" + "WL_DISCONNECTED = 7\n" ); } diff --git a/tests/device/test_spi_flash/test_spi_flash.ino b/tests/device/test_spi_flash/test_spi_flash.ino new file mode 100644 index 000000000..fa7ea767b --- /dev/null +++ b/tests/device/test_spi_flash/test_spi_flash.ino @@ -0,0 +1,187 @@ +#include +#include + +BS_ENV_DECLARE(); + +void preinit() { + // (no C++ in function) + // disable wifi + ESP8266WiFiClass::preinitWiFiOff(); +} + +void setup() +{ + Serial.begin(115200); + BS_RUN(Serial); +} + +bool pretest() +{ + return true; +} + +bool compareBuffers(uint32_t *first, uint32_t *second, size_t offset, size_t len) +{ + uint8_t *firstBytes = (uint8_t *)first; + uint8_t *secondBytes = (uint8_t *)second; + + for (size_t i = offset; i < offset + len; i++) + { + if (firstBytes[i] != secondBytes[i]) + { + Serial.printf("Compare fail @ %u\n", i); + for (size_t j = i & ~3; j < (i & ~3) + 4; j++) + { + Serial.printf("%02x ", firstBytes[j]); + } + Serial.println(); + for (size_t j = i & ~3; j < (i & ~3) + 4; j++) + { + Serial.printf("%02x ", secondBytes[j]); + } + Serial.println(); + return false; + } + } + return true; +} + +bool testFlash(uint32_t start_offset, uint8_t data_offset, size_t amount) +{ + static uint32_t *write_buffer = (uint32_t *)malloc(4096); + static uint32_t *read_buffer = (uint32_t *)malloc(4096); + + for (uint32_t i = 0; i < 1024; i++) + { + write_buffer[i] = (i + 100) * 33; + read_buffer[i] = 0xAAAAAAAA; + } + Serial.println("---------------------------------------------------"); + ESP.flashEraseSector(start_offset / 0x1000); + Serial.printf("Testing %d bytes @ %08x + %d\n", amount, start_offset, data_offset); + unsigned long start = micros(); + + if (!ESP.flashWrite(start_offset, (uint8_t *)write_buffer + data_offset, amount)) + { + Serial.printf("Write fail\n"); + return false; + } + if (!ESP.flashRead(start_offset, (uint8_t *)read_buffer + data_offset, amount)) + { + Serial.printf("Read fail\n"); + return false; + } + if (!compareBuffers(write_buffer, read_buffer, data_offset, amount)) + { + return false; + } + Serial.printf("Write took %lu us\n", micros() - start); + return true; +} + +// Columns in test case names are as following: +// 1. Offset -> +o (4 byte aligned), -o (unaligned) +// 2. Memory pointer -> +m (4 byte aligned), -m (unaligned) +// 3. Size -> +s (4 byte ), -s (unaligned) +// 4. Number of pages crossed -> np + +// Aligned offset +// Aligned memory +// Aligned size +TEST_CASE("|+o|+m|+s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 0, 100)); +} +TEST_CASE("|+o|+m|+s|1p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 0, 512)); +} +// Unaligned size +TEST_CASE("|+o|+m|-s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 0, 101)); +} +TEST_CASE("|+o|+m|-s|2p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 0, 515)); +} +// Unaligned memory +// Aligned size +TEST_CASE("|+o|-m|+s|0|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 1, 100)); +} +TEST_CASE("|+o|-m|+s|1p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 3, 512)); +} +// Unaligned size +TEST_CASE("|+o|-m|-s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 2, 101)); +} +TEST_CASE("|+o|-m|-s|2p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0000, 1, 515)); +} +// Unaligned offset +// Aligned memory +// Aligned size +TEST_CASE("|-o|+m|+s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 0, 100)); +} +TEST_CASE("|-o|+m|+s|1p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 0, 260)); +} +// Unaligned size +TEST_CASE("|-o|+m|-s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 0, 105)); +} +TEST_CASE("|-o|+m|-s|1p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 0, 271)); +} +// Unaligned memory +// Aligned size +TEST_CASE("|-o|-m|+s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 1, 100)); +} +TEST_CASE("|-o|-m|+s|1p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 2, 260)); +} +// Unaligned size +TEST_CASE("|-o|-m|-s|0p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 3, 105)); +} +TEST_CASE("|-o|-m|-s|1p|", "[spi_flash]") +{ + CHECK(testFlash(0xa0001, 1, 271)); +} + +TEST_CASE("Last bytes of page", "[spi_flash]") +{ + CHECK(testFlash(0xa0000 + 255, 0, 1)); + CHECK(testFlash(0xa0000 + 255, 1, 1)); + CHECK(testFlash(0xa0000 + 254, 0, 2)); + CHECK(testFlash(0xa0000 + 254, 1, 2)); + CHECK(testFlash(0xa0000 + 253, 0, 3)); + CHECK(testFlash(0xa0000 + 253, 1, 3)); +} + +TEST_CASE("Unaligned page cross only", "[spi_flash]") +{ + CHECK(testFlash(0xa0000 + 254, 0, 3)); + CHECK(testFlash(0xa0000 + 254, 1, 3)); + CHECK(testFlash(0xa0000 + 255, 0, 2)); + CHECK(testFlash(0xa0000 + 255, 1, 2)); +} + +void loop () +{ +} diff --git a/tests/device/test_sw_arduino_math_overrides/test_sw_arduino_math_overrides.ino b/tests/device/test_sw_arduino_math_overrides/test_sw_arduino_math_overrides.ino new file mode 100644 index 000000000..49496ab7a --- /dev/null +++ b/tests/device/test_sw_arduino_math_overrides/test_sw_arduino_math_overrides.ino @@ -0,0 +1,86 @@ +/* + Small math example, checking whether we properly integrate with c++ math + + ref: + - https://github.com/esp8266/Arduino/issues/5530 + - https://github.com/espressif/arduino-esp32/pull/2738 + + Released to public domain +*/ + +#include +#include + +BS_ENV_DECLARE(); + +void setup() +{ + Serial.begin(115200); + BS_RUN(Serial); +} + +bool pretest() +{ + return true; +} + +#define TEST_MATH_IS_SAME(OP1, OP2) \ + std::is_same::value + +TEST_CASE("std::abs and abs result is the same", "[arduino-math]") +{ + CHECK(TEST_MATH_IS_SAME(abs(-5), std::abs(-5))); + CHECK(TEST_MATH_IS_SAME(abs(-25.0), std::abs(-25.0))); + CHECK(TEST_MATH_IS_SAME(abs(10.0), std::abs(10.0))); + CHECK(! TEST_MATH_IS_SAME(abs(10.0), std::abs(10))); + CHECK(! TEST_MATH_IS_SAME(abs(-5), std::abs(10.0))); +} + +TEST_CASE("abs works with ints", "[arduino-math]") +{ + int a = -3; + int b = 3; + CHECK(TEST_MATH_IS_SAME(abs(a), a)); + CHECK(TEST_MATH_IS_SAME(abs(b), b)); + CHECK(abs(a) == b); + CHECK(abs(b) == b); +} + +template +bool compare_floats(T a, T b) { + static_assert(std::is_floating_point::value, ""); + return std::fabs(a - b) < std::numeric_limits::epsilon(); +} + +TEST_CASE("abs works with floats", "[arduino-math]") +{ + float a = -3.5; + float b = 3.5; + CHECK(TEST_MATH_IS_SAME(abs(a), a)); + CHECK(TEST_MATH_IS_SAME(abs(b), b)); + CHECK(compare_floats(abs(a), b)); + CHECK(compare_floats(abs(b), b)); +} + +TEST_CASE("round works with ints", "[arduino-math]") +{ + int a = 5; + int b = 10; + CHECK(TEST_MATH_IS_SAME(round(a), std::round(a))); + CHECK(TEST_MATH_IS_SAME(round(b), std::round(b))); + CHECK(compare_floats(round(a), std::round(a))); + CHECK(compare_floats(round(b), std::round(b))); +} + +TEST_CASE("round works with floats", "[arduino-math]") +{ + float a = 2.9; + float b = 3.0; + CHECK(TEST_MATH_IS_SAME(round(a), a)); + CHECK(TEST_MATH_IS_SAME(round(b), b)); + CHECK(compare_floats(round(a), b)); + CHECK(compare_floats(round(b), b)); +} + +void loop(){} + diff --git a/tests/host/Makefile b/tests/host/Makefile index dabab58e7..410dc3fb0 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -174,6 +174,7 @@ FLAGS += -DHTTPCLIENT_1_1_COMPATIBLE=0 FLAGS += -DLWIP_IPV6=0 FLAGS += -DHOST_MOCK=1 FLAGS += -DNONOSDK221=1 +FLAGS += -DF_CPU=80000000 FLAGS += $(MKFLAGS) FLAGS += -Wimplicit-fallthrough=2 # allow "// fall through" comments to stop spurious warnings FLAGS += $(USERCFLAGS) @@ -267,6 +268,7 @@ ARDUINO_LIBS := \ IPAddress.cpp \ Updater.cpp \ base64.cpp \ + LwipIntfCB.cpp \ ) \ $(addprefix ../../libraries/ESP8266WiFi/src/,\ ESP8266WiFi.cpp \ diff --git a/tests/host/common/Arduino.h b/tests/host/common/Arduino.h deleted file mode 100644 index 8735ecba6..000000000 --- a/tests/host/common/Arduino.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - Arduino.h - Main include file for the Arduino SDK - Copyright (c) 2005-2013 Arduino Team. All right reserved. - - 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 - */ - -#ifndef Arduino_h -#define Arduino_h - -#define MOCK "(mock) " - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "binary.h" -#include "twi.h" -#include "core_esp8266_features.h" - -#define HIGH 0x1 -#define LOW 0x0 - -#define PWMRANGE 1023 - - //GPIO FUNCTIONS -#define INPUT 0x00 -#define INPUT_PULLUP 0x02 -#define INPUT_PULLDOWN_16 0x04 // PULLDOWN only possible for pin16 -#define OUTPUT 0x01 -#define OUTPUT_OPEN_DRAIN 0x03 -#define WAKEUP_PULLUP 0x05 -#define WAKEUP_PULLDOWN 0x07 -#define SPECIAL 0xF8 //defaults to the usable BUSes uart0rx/tx uart1tx and hspi -#define FUNCTION_0 0x08 -#define FUNCTION_1 0x18 -#define FUNCTION_2 0x28 -#define FUNCTION_3 0x38 -#define FUNCTION_4 0x48 - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 -#define EULER 2.718281828459045235360287471352 - -#define SERIAL 0x0 -#define DISPLAY 0x1 - -#define LSBFIRST 0 -#define MSBFIRST 1 - - //Interrupt Modes -#define DISABLED 0x00 -#define RISING 0x01 -#define FALLING 0x02 -#define CHANGE 0x03 -#define ONLOW 0x04 -#define ONHIGH 0x05 -#define ONLOW_WE 0x0C -#define ONHIGH_WE 0x0D - -#define DEFAULT 1 -#define EXTERNAL 0 - - //timer dividers -#define TIM_DIV1 0 //80MHz (80 ticks/us - 104857.588 us max) -#define TIM_DIV16 1 //5MHz (5 ticks/us - 1677721.4 us max) -#define TIM_DIV265 3 //312.5Khz (1 tick = 3.2us - 26843542.4 us max) - //timer int_types -#define TIM_EDGE 0 -#define TIM_LEVEL 1 - //timer reload values -#define TIM_SINGLE 0 //on interrupt routine you need to write a new value to start the timer again -#define TIM_LOOP 1 //on interrupt the counter will start with the same value again - -#define timer1_read() (T1V) -#define timer1_enabled() ((T1C & (1 << TCTE)) != 0) -#define timer1_interrupted() ((T1C & (1 << TCIS)) != 0) - - typedef void(*timercallback)(void); - - void timer1_isr_init(void); - void timer1_enable(uint8_t divider, uint8_t int_type, uint8_t reload); - void timer1_disable(void); - void timer1_attachInterrupt(timercallback userFunc); - void timer1_detachInterrupt(void); - void timer1_write(uint32_t ticks); //maximum ticks 8388607 - - // timer0 is a special CPU timer that has very high resolution but with - // limited control. - // it uses CCOUNT (ESP.GetCycleCount()) as the non-resetable timer counter - // it does not support divide, type, or reload flags - // it is auto-disabled when the compare value matches CCOUNT - // it is auto-enabled when the compare value changes -#define timer0_interrupted() (ETS_INTR_PENDING() & (_BV(ETS_COMPARE0_INUM))) -#define timer0_read() ((__extension__({uint32_t count;__asm__ __volatile__("esync; rsr %0,ccompare0":"=a" (count));count;}))) -#define timer0_write(count) __asm__ __volatile__("wsr %0,ccompare0; esync"::"a" (count) : "memory") - - void timer0_isr_init(void); - void timer0_attachInterrupt(timercallback userFunc); - void timer0_detachInterrupt(void); - - // undefine stdlib's abs if encountered -#ifdef abs -#undef abs -#endif - -#define abs(x) ((x)>0?(x):-(x)) -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) -#define radians(deg) ((deg)*DEG_TO_RAD) -#define degrees(rad) ((rad)*RAD_TO_DEG) -#define sq(x) ((x)*(x)) - - void ets_intr_lock(); - void ets_intr_unlock(); - -#ifndef __STRINGIFY -#define __STRINGIFY(a) #a -#endif - -#define xt_rsil(level) (level) -#define xt_wsr_ps(state) do { (void)(state); } while (0) - -#define interrupts() xt_rsil(0) -#define noInterrupts() xt_rsil(15) - -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) -#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) - -#define lowByte(w) ((uint8_t) ((w) & 0xff)) -#define highByte(w) ((uint8_t) ((w) >> 8)) - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) - - // avr-libc defines _NOP() since 1.6.2 -#ifndef _NOP -#define _NOP() do { __asm__ volatile ("nop"); } while (0) -#endif - - typedef unsigned int word; - -#define bit(b) (1UL << (b)) -#define _BV(b) (1UL << (b)) - - typedef uint8_t boolean; - typedef uint8_t byte; - - void init(void); - void initVariant(void); - - void pinMode(uint8_t pin, uint8_t mode); - void digitalWrite(uint8_t pin, uint8_t val); - int digitalRead(uint8_t pin); - int analogRead(uint8_t pin); - void analogReference(uint8_t mode); - void analogWrite(uint8_t pin, int val); - void analogWriteFreq(uint32_t freq); - void analogWriteRange(uint32_t range); - - unsigned long millis(void); - unsigned long micros(void); - void delay(unsigned long); - void delayMicroseconds(unsigned int us); - unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); - unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout); - - void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); - uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); - - void attachInterrupt(uint8_t pin, void (*)(void), int mode); - void detachInterrupt(uint8_t pin); - - void setup(void); - void loop(void); - - void yield(void); - void esp_yield(void); - void optimistic_yield(uint32_t interval_us); - -#define digitalPinToPort(pin) (0) -#define digitalPinToBitMask(pin) (1UL << (pin)) -#define digitalPinToTimer(pin) (0) -#define portOutputRegister(port) ((volatile uint32_t*) &GPO) -#define portInputRegister(port) ((volatile uint32_t*) &GPI) -#define portModeRegister(port) ((volatile uint32_t*) &GPE) - -#define NOT_A_PIN -1 -#define NOT_A_PORT -1 -#define NOT_AN_INTERRUPT -1 -#define NOT_ON_TIMER 0 - -#ifdef __cplusplus -} // extern "C" -#endif - -#ifdef __cplusplus - -#include - -#include "WCharacter.h" -#include "WString.h" - -#include "HardwareSerial.h" -#include "Esp.h" -#include "Updater.h" -#include "debug.h" - -#if 0 -#ifndef _GLIBCXX_VECTOR -// arduino is not compatible with std::vector -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) -#endif -#endif - -#define _min(a,b) ((a)<(b)?(a):(b)) -#define _max(a,b) ((a)>(b)?(a):(b)) - -uint16_t makeWord(uint16_t w); -uint16_t makeWord(byte h, byte l); - -#define word(...) makeWord(__VA_ARGS__) - -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); -unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); -void noTone(uint8_t _pin); - -// WMath prototypes -long random(long); -long random(long, long); -void randomSeed(unsigned long); -long map(long, long, long, long, long); - -extern "C" void configTime(long timezone, int daylightOffset_sec, - const char* server1, const char* server2 = nullptr, const char* server3 = nullptr); - -#endif - -#include "pins_arduino.h" - -#endif /* Arduino_h */ - -#if __cplusplus -#include -#include -#define MOCKARGS 1 -extern std::map mockArgs; -#endif diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 637235968..a9d8d696f 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -56,8 +56,6 @@ const char* fspath = nullptr; static struct termios initial_settings; -std::map mockArgs; - int mockverbose (const char* fmt, ...) { va_list ap; @@ -137,8 +135,6 @@ void help (const char* argv0, int exitcode) "\t-S - spiffs size in KBytes (default: %zd)\n" "\t-L - littlefs size in KBytes (default: %zd)\n" "\t (spiffs, littlefs: negative value will force mismatched size)\n" - "\t-K - key\n" - "\t-V - value\n" "\tgeneral:\n" "\t-c - ignore CTRL-C (send it via Serial)\n" "\t-f - no throttle (possibly 100%%CPU)\n" @@ -162,8 +158,6 @@ static struct option options[] = { "spiffskb", required_argument, NULL, 'S' }, { "littlefskb", required_argument, NULL, 'L' }, { "portshifter", required_argument, NULL, 's' }, - { "key", required_argument, NULL, 'K' }, - { "value", required_argument, NULL, 'V' }, { "once", no_argument, NULL, '1' }, }; @@ -215,11 +209,10 @@ int main (int argc, char* const argv []) mock_port_shifter = 0; else mock_port_shifter = MOCK_PORT_SHIFTER; - String key; for (;;) { - int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1K:V:", options, NULL); + int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1", options, NULL); if (n < 0) break; switch (n) @@ -260,12 +253,6 @@ int main (int argc, char* const argv []) case 'T': serial_timestamp = true; break; - case 'K': - key = optarg; - break; - case 'V': - mockArgs[key] = optarg; - break; case '1': run_once = true; break; diff --git a/tests/host/common/MockEsp.cpp b/tests/host/common/MockEsp.cpp index 2045523e8..4394c4162 100644 --- a/tests/host/common/MockEsp.cpp +++ b/tests/host/common/MockEsp.cpp @@ -159,7 +159,15 @@ FlashMode_t EspClass::magicFlashChipMode(uint8_t byte) return FM_DOUT; } -bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) +bool EspClass::flashWrite(uint32_t offset, const uint32_t *data, size_t size) +{ + (void)offset; + (void)data; + (void)size; + return true; +} + +bool EspClass::flashWrite(uint32_t offset, const uint8_t *data, size_t size) { (void)offset; (void)data; @@ -175,6 +183,14 @@ bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size) return true; } +bool EspClass::flashRead(uint32_t offset, uint8_t *data, size_t size) +{ + (void)offset; + (void)data; + (void)size; + return true; +} + uint32_t EspClass::magicFlashChipSize(uint8_t byte) { switch(byte & 0x0F) { case 0x0: // 4 Mbit (512KB) diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp index a2d72081d..5eb7969de 100644 --- a/tests/host/common/MockTools.cpp +++ b/tests/host/common/MockTools.cpp @@ -53,16 +53,6 @@ int ets_printf (const char* fmt, ...) return len; } -extern "C" void configTime(long timezone, int daylightOffset_sec, - const char* server1, const char* server2, const char* server3) -{ - (void)server1; - (void)server2; - (void)server3; - - mockverbose("configTime: TODO (tz=%ldH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec); -} - void stack_thunk_add_ref() { } void stack_thunk_del_ref() { } void stack_thunk_repaint() { } @@ -78,3 +68,13 @@ void stack_thunk_dump_stack() { } #define make_stack_thunk(fcnToThunk) }; + +void configTime(int timezone, int daylightOffset_sec, + const char* server1, const char* server2, const char* server3) +{ + (void)server1; + (void)server2; + (void)server3; + + mockverbose("configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec); +} diff --git a/tests/host/common/esp8266_peri.h b/tests/host/common/esp8266_peri.h index d9dfd50ed..4a1a3cd03 100644 --- a/tests/host/common/esp8266_peri.h +++ b/tests/host/common/esp8266_peri.h @@ -6,4 +6,4 @@ const int GPI = 0; const int GPO = 0; const int GP16I = 0; -#endif \ No newline at end of file +#endif diff --git a/tests/host/common/littlefs_mock.cpp b/tests/host/common/littlefs_mock.cpp index 73629787a..0d99e82b1 100644 --- a/tests/host/common/littlefs_mock.cpp +++ b/tests/host/common/littlefs_mock.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "flash_hal_mock.h" #define LITTLEFS_FILE_NAME "littlefs.bin" diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index eff32dd46..f96194a34 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -30,6 +30,7 @@ */ #define CORE_MOCK 1 +#define MOCK "(mock) " // TODO: provide common logging API instead of adding this string everywhere? // @@ -37,7 +38,6 @@ #define ESP8266 1 #define A0 0 #define LED_BUILTIN 0 -#define F_CPU 80000000 #define LWIP_OPEN_SRC #define TCP_MSS 536 #define LWIP_FEATURES 1 @@ -54,28 +54,23 @@ #define D7 7 #define D8 8 -// include host's STL before any other include file -// because core definition like max() is in the way - -#ifdef __cplusplus -#include -#endif #include - #ifdef __cplusplus extern "C" { #endif -//#include +// TODO: #include ? char* itoa (int val, char *s, int radix); char* ltoa (long val, char *s, int radix); -#ifdef __cplusplus -} -#endif + size_t strlcat(char *dst, const char *src, size_t size); size_t strlcpy(char *dst, const char *src, size_t size); +#ifdef __cplusplus +} +#endif + // exotic typedefs used in the sdk #include @@ -91,9 +86,6 @@ uint32_t esp_get_cycle_count(); #include -// - -#include #define RANDOM_REG32 ((uint32_t)random()) // net tweak diff --git a/tests/host/common/spiffs_mock.cpp b/tests/host/common/spiffs_mock.cpp index d32c56d9d..c7f9f53ab 100644 --- a/tests/host/common/spiffs_mock.cpp +++ b/tests/host/common/spiffs_mock.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "flash_hal_mock.h" diff --git a/tools/sdk/include/spi_flash_geometry.h b/tools/sdk/include/spi_flash_geometry.h index bb8c0ea22..d6d7cf16d 100644 --- a/tools/sdk/include/spi_flash_geometry.h +++ b/tools/sdk/include/spi_flash_geometry.h @@ -7,6 +7,7 @@ #define FLASH_SECTOR_SIZE 0x1000 #define FLASH_BLOCK_SIZE 0x10000 +#define FLASH_PAGE_SIZE 0x100 #define APP_START_OFFSET 0x1000 //pulled this define from spi_flash.h for reuse in the Arduino core without pulling in a bunch of other stuff diff --git a/tools/signing.py b/tools/signing.py index 8fef38a11..40405288c 100755 --- a/tools/signing.py +++ b/tools/signing.py @@ -74,6 +74,13 @@ def main(): outdir = os.path.dirname(args.out) if not os.path.exists(outdir): os.makedirs(outdir) + try: + with open(args.out, "r") as inp: + old_val = inp.read() + if old_val == val: + return + except Exception: + pass with open(args.out, "w") as f: f.write(val) return 0