From 8af9f762c501df1006049704c3896382ebc2410a Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 17 Oct 2020 10:28:27 -0700 Subject: [PATCH 1/4] Add Print::availableForWrite method Adds an availableForWrite() method to the Print class, matching current ArduinoCore-API commit 398e70f188e2b861c10d9ffe5e2bfcb6a4a4f489 . Hook availableForWrite into the SDFS filesystem (other FSes don't have this capability built-in). Fixes #7650 --- cores/esp8266/FS.cpp | 8 ++++++++ cores/esp8266/FS.h | 1 + cores/esp8266/FSImpl.h | 1 + cores/esp8266/Print.h | 4 ++++ libraries/SDFS/src/SDFS.h | 5 +++++ 5 files changed, 19 insertions(+) diff --git a/cores/esp8266/FS.cpp b/cores/esp8266/FS.cpp index 392955d492..d73be017a3 100644 --- a/cores/esp8266/FS.cpp +++ b/cores/esp8266/FS.cpp @@ -46,6 +46,14 @@ int File::available() { return _p->size() - _p->position(); } +int File::availableForWrite() { + if (!_p) + return false; + + return _p->availableForWrite(); +} + + int File::read() { if (!_p) return -1; diff --git a/cores/esp8266/FS.h b/cores/esp8266/FS.h index 93ef68ed5a..b1f1c528aa 100644 --- a/cores/esp8266/FS.h +++ b/cores/esp8266/FS.h @@ -57,6 +57,7 @@ class File : public Stream // Print methods: size_t write(uint8_t) override; size_t write(const uint8_t *buf, size_t size) override; + int availableForWrite() override; // Stream methods: int available() override; diff --git a/cores/esp8266/FSImpl.h b/cores/esp8266/FSImpl.h index 1a3566f2cb..373b26f2ca 100644 --- a/cores/esp8266/FSImpl.h +++ b/cores/esp8266/FSImpl.h @@ -35,6 +35,7 @@ class FileImpl { virtual bool seek(uint32_t pos, SeekMode mode) = 0; virtual size_t position() const = 0; virtual size_t size() const = 0; + virtual int availableForWrite() { return 0; } virtual bool truncate(uint32_t size) = 0; virtual void close() = 0; virtual const char* name() const = 0; diff --git a/cores/esp8266/Print.h b/cores/esp8266/Print.h index 5517553999..6b2faed6e6 100644 --- a/cores/esp8266/Print.h +++ b/cores/esp8266/Print.h @@ -75,6 +75,10 @@ class Print { inline size_t write(char c) { return write((uint8_t) c); } inline size_t write(int8_t c) { return write((uint8_t) c); } + // default to zero, meaning "a single write may block" + // should be overriden by subclasses with buffering + virtual int availableForWrite() { return 0; } + size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); size_t printf_P(PGM_P format, ...) __attribute__((format(printf, 2, 3))); size_t print(const __FlashStringHelper *); diff --git a/libraries/SDFS/src/SDFS.h b/libraries/SDFS/src/SDFS.h index a884552ffc..d92d400923 100644 --- a/libraries/SDFS/src/SDFS.h +++ b/libraries/SDFS/src/SDFS.h @@ -268,6 +268,11 @@ class SDFSFileImpl : public FileImpl close(); } + int availableForWrite() override + { + return _opened ? _fd->availableForWrite() : 0; + } + size_t write(const uint8_t *buf, size_t size) override { return _opened ? _fd->write(buf, size) : -1; From 31c99b453d55e38a692e3d24204f6d6dada43849 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 17 Oct 2020 10:53:04 -0700 Subject: [PATCH 2/4] WiFiClient::availableForWrite proto matching Print --- libraries/ESP8266WiFi/src/WiFiClient.cpp | 2 +- libraries/ESP8266WiFi/src/WiFiClient.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index 1663a29ecb..825f2ed839 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -195,7 +195,7 @@ bool WiFiClient::getSync() const return _client->getSync(); } -size_t WiFiClient::availableForWrite () +int WiFiClient::availableForWrite () { return _client? _client->availableForWrite(): 0; } diff --git a/libraries/ESP8266WiFi/src/WiFiClient.h b/libraries/ESP8266WiFi/src/WiFiClient.h index 31f6d105a7..50112c2f94 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/libraries/ESP8266WiFi/src/WiFiClient.h @@ -86,7 +86,7 @@ class WiFiClient : public Client, public SList { static void setLocalPortStart(uint16_t port) { _localPort = port; } - size_t availableForWrite(); + int availableForWrite() override; friend class WiFiServer; From 1649262701c39d48945a74b8f47eda8d648c27df Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 17 Oct 2020 11:01:45 -0700 Subject: [PATCH 3/4] Fix Netdump signedness warning --- libraries/Netdump/src/Netdump.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Netdump/src/Netdump.cpp b/libraries/Netdump/src/Netdump.cpp index a608a1c3b2..4d6a9f42dc 100644 --- a/libraries/Netdump/src/Netdump.cpp +++ b/libraries/Netdump/src/Netdump.cpp @@ -176,7 +176,7 @@ void Netdump::tcpDumpProcess(const Packet& np) bufferIndex += incl_len; } - if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= bufferIndex) + if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= (int)bufferIndex) { tcpDumpClient.write(packetBuffer, bufferIndex); bufferIndex = 0; @@ -202,7 +202,7 @@ void Netdump::tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf) { setCallback(nullptr); } - if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= bufferIndex) + if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= (int)bufferIndex) { tcpDumpClient.write(packetBuffer, bufferIndex); bufferIndex = 0; From 075b905f53a4576fc4a6eb839bc2397d0e54ebc3 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 17 Oct 2020 11:12:59 -0700 Subject: [PATCH 4/4] Clean up Serial availableForWrite This is evidently a breaking change due to the type difference. Arduino's `availableForWrite` returns an `int`, while the (multiply-implemented, non-virtual) core `availableForWrite` returned `size_t`. --- cores/esp8266/HardwareSerial.h | 2 +- .../examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/HardwareSerial.h b/cores/esp8266/HardwareSerial.h index 6b89f68007..940bde173b 100644 --- a/cores/esp8266/HardwareSerial.h +++ b/cores/esp8266/HardwareSerial.h @@ -150,7 +150,7 @@ class HardwareSerial: public Stream { return readBytes((char*)buffer, size); } - int availableForWrite(void) + int availableForWrite(void) override { return static_cast(uart_tx_free(_uart)); } diff --git a/libraries/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino b/libraries/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino index 9102af12d8..46a4f277dd 100644 --- a/libraries/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino +++ b/libraries/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino @@ -173,10 +173,10 @@ void loop() { // determine maximum output size "fair TCP use" // client.availableForWrite() returns 0 when !client.connected() - size_t maxToTcp = 0; + int maxToTcp = 0; for (int i = 0; i < MAX_SRV_CLIENTS; i++) if (serverClients[i]) { - size_t afw = serverClients[i].availableForWrite(); + int afw = serverClients[i].availableForWrite(); if (afw) { if (!maxToTcp) { maxToTcp = afw; @@ -190,11 +190,11 @@ void loop() { } //check UART for data - size_t len = std::min((size_t)Serial.available(), maxToTcp); + size_t len = std::min(Serial.available(), maxToTcp); len = std::min(len, (size_t)STACK_PROTECTOR); if (len) { uint8_t sbuf[len]; - size_t serial_got = Serial.readBytes(sbuf, len); + int serial_got = Serial.readBytes(sbuf, len); // push UART data to all connected telnet clients for (int i = 0; i < MAX_SRV_CLIENTS; i++) // if client.availableForWrite() was 0 (congested)