diff --git a/README.md b/README.md index 507d90c..910df10 100644 --- a/README.md +++ b/README.md @@ -151,9 +151,13 @@ SoftwareSerial | ❌ SPI | ❌ Wire | ❌ **OTHER LIBRARIES** | +Wi-Fi Station | ✔️ +Wi-Fi Access Point | ❌ +Wi-Fi Events | ❌ +Wi-Fi Client (SSL) | ✔️ (❌) +Wi-Fi Server | ❌ SPIFFS | ❌ BLE | - -Wi-Fi (SSL) | ✔️ (❌) HTTP | ❌ NTP | ❌ OTA | ❌ diff --git a/arduino/libretuya/api/WiFiClient.h b/arduino/libretuya/api/WiFiClient.h index 32dcb0d..562a59b 100644 --- a/arduino/libretuya/api/WiFiClient.h +++ b/arduino/libretuya/api/WiFiClient.h @@ -28,6 +28,10 @@ class IWiFiClient : public Client { IWiFiClient(int sock) {} + ~IWiFiClient() { + stop(); + } + virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0; virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0; @@ -66,4 +70,5 @@ class IWiFiClient : public Client { virtual uint16_t localPort(int sock) const = 0; using Print::write; + using Client::stop; }; diff --git a/arduino/libretuya/api/WiFiServer.h b/arduino/libretuya/api/WiFiServer.h index d18ff46..279fb6e 100644 --- a/arduino/libretuya/api/WiFiServer.h +++ b/arduino/libretuya/api/WiFiServer.h @@ -20,39 +20,47 @@ #pragma once #include -#include +#include #include "WiFiClient.h" -class IWiFiServer : public Server { +#include + +template ::value>> + +class IWiFiServer : public Print { // arduino::Server is useless anyway public: void listenOnLocalhost() {} - IWiFiServer(uint16_t port = 80, uint8_t max_clients = 4) {} + IWiFiServer(uint16_t port = 80, uint8_t maxClients = 4) {} ~IWiFiServer() { - end(); + stop(); } - WiFiClient available(); - - WiFiClient accept() { - return available(); - } + TWiFiClient available() { + return accept(); + }; virtual operator bool() = 0; - void begin(uint16_t port = 0); - void begin(uint16_t port, int reuse_enable); - void end(); - void close(); - void stop(); + virtual bool begin(uint16_t port = 0, bool reuseAddr = true) = 0; + virtual void end() = 0; + virtual TWiFiClient accept() = 0; - int setTimeout(uint32_t seconds); - void stopAll(); - void setNoDelay(bool nodelay); - bool getNoDelay(); - bool hasClient(); + void close() { + end(); + } + + void stop() { + end(); + } + + virtual int setTimeout(uint32_t seconds) = 0; + virtual void stopAll() = 0; + virtual void setNoDelay(bool noDelay) = 0; + virtual bool getNoDelay() = 0; + virtual bool hasClient() = 0; size_t write(uint8_t data) { return write(&data, 1); diff --git a/arduino/libretuya/compat/WiFiAP.h b/arduino/libretuya/compat/WiFiAP.h new file mode 100644 index 0000000..42faf3d --- /dev/null +++ b/arduino/libretuya/compat/WiFiAP.h @@ -0,0 +1,5 @@ +#pragma once + +// ESP32 WiFi examples use WiFiAP.h include + +#include diff --git a/arduino/realtek-ambz/cores/arduino/rtl_sys.cpp b/arduino/realtek-ambz/cores/arduino/rtl_sys.cpp index b72a0ad..8d7dcdc 100644 --- a/arduino/realtek-ambz/cores/arduino/rtl_sys.cpp +++ b/arduino/realtek-ambz/cores/arduino/rtl_sys.cpp @@ -29,6 +29,7 @@ extern "C" { #include extern void *pvPortMalloc( size_t xWantedSize ); +extern void *os_zalloc( size_t xWantedSize ); extern void vPortFree( void *pv ); extern void *pvPortReAlloc( void *pv, size_t xWantedSize ); extern size_t xPortGetFreeHeapSize( void ); @@ -79,7 +80,7 @@ void sys_info(void) { } -void * malloc(size_t size) +/* void * malloc(size_t size) { void * ret; if((ret = pvPortMalloc(size)) == NULL) @@ -99,7 +100,7 @@ void * zalloc(size_t size) void *calloc(size_t count, size_t size) { return zalloc(count * size); -} +} */ void free(void *pv) { diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFi.h b/arduino/realtek-ambz/libraries/WiFi/WiFi.h index 136b7b8..82bfa38 100644 --- a/arduino/realtek-ambz/libraries/WiFi/WiFi.h +++ b/arduino/realtek-ambz/libraries/WiFi/WiFi.h @@ -16,6 +16,7 @@ extern "C" { #endif #include "WiFiClient.h" +#include "WiFiServer.h" class WiFiClass : public IWiFiClass, public IWiFiGenericClass, diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiAP.cpp b/arduino/realtek-ambz/libraries/WiFi/WiFiAP.cpp index 2a34824..96d78d7 100644 --- a/arduino/realtek-ambz/libraries/WiFi/WiFiAP.cpp +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiAP.cpp @@ -21,9 +21,9 @@ bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bo if (passphrase) { strcpy((char *)ap_password, passphrase); - wifi.security_type = RTW_SECURITY_WPA2_AES_PSK; - wifi.password = ap_password; - wifi.password_len = strlen(passphrase); + ap.security_type = RTW_SECURITY_WPA2_AES_PSK; + ap.password = ap_password; + ap.password_len = strlen(passphrase); } dhcps_deinit(); @@ -96,6 +96,7 @@ bool WiFiClass::softAPdisconnect(bool wifiOff) { uint8_t WiFiClass::softAPgetStationNum() { // TODO + // the struct is at wifi_conf.c:2576 return 0; } diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiClient.cpp b/arduino/realtek-ambz/libraries/WiFi/WiFiClient.cpp index 4d2b074..5ab2a0f 100644 --- a/arduino/realtek-ambz/libraries/WiFi/WiFiClient.cpp +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiClient.cpp @@ -1,38 +1,27 @@ #include "WiFiClient.h" #include "WiFiPriv.h" -// I think I don't understand how that works. -// For some reason, LwIP uses a different (extern) errno, -// while this macro refers to a function __errno, which -// reads a totally different variable. -#undef errno -#include - -// disable #defines removing lwip_ prefix -#undef LWIP_COMPAT_SOCKETS -#define LWIP_COMPAT_SOCKETS 0 -#include - -WiFiClient::WiFiClient() : _sock(-1), _connected(false) { - _timeout = WIFI_CLIENT_CONNECT_TIMEOUT; +WiFiClient::WiFiClient() { + DiagPrintf("WiFiClient()\r\n"); + _sock = -1; + _connected = false; + _rxBuffer = NULL; + _timeout = WIFI_CLIENT_CONNECT_TIMEOUT; } WiFiClient::WiFiClient(int sock) { _sock = sock; _connected = true; - _rxBuffer.reset(new LwIPRxBuffer(sock)); - _timeout = WIFI_CLIENT_CONNECT_TIMEOUT; -} - -WiFiClient::~WiFiClient() { - stop(); + _rxBuffer = new LwIPRxBuffer(sock); + _timeout = WIFI_CLIENT_CONNECT_TIMEOUT; } WiFiClient &WiFiClient::operator=(const IWiFiClient &other) { stop(); - // _sock = other._sock; - // _connected = other._connected; - // _rxBuffer = other._rxBuffer; + WiFiClient *oth = (WiFiClient *)&other; + _sock = oth->_sock; + _connected = oth->_connected; + _rxBuffer = oth->_rxBuffer; return *this; } @@ -115,7 +104,8 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) { lwip_close(_sock); _sock = sock; _connected = true; - _rxBuffer.reset(new LwIPRxBuffer(_sock)); + free(_rxBuffer); + _rxBuffer = new LwIPRxBuffer(_sock); return 1; } @@ -264,7 +254,8 @@ void WiFiClient::stop() { lwip_close(_sock); _sock = -1; _connected = false; - _rxBuffer = NULL; + free(_rxBuffer); + _rxBuffer = NULL; } uint8_t WiFiClient::connected() { @@ -292,7 +283,7 @@ uint8_t WiFiClient::connected() { return _connected; } -IPAddress getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) { +IPAddress __attribute__((noinline)) getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) { struct sockaddr addr; socklen_t len = sizeof(addr); func(sock, &addr, &len); @@ -300,7 +291,7 @@ IPAddress getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) { return IPAddress((uint32_t)(s->sin_addr.s_addr)); } -uint16_t getport(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) { +uint16_t __attribute__((noinline)) getport(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) { struct sockaddr addr; socklen_t len = sizeof(addr); func(sock, &addr, &len); diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiClient.h b/arduino/realtek-ambz/libraries/WiFi/WiFiClient.h index bfe4607..3c69aef 100644 --- a/arduino/realtek-ambz/libraries/WiFi/WiFiClient.h +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiClient.h @@ -2,18 +2,16 @@ #include #include -#include class WiFiClient : public IWiFiClient { private: int _sock; bool _connected; - std::shared_ptr _rxBuffer; + LwIPRxBuffer *_rxBuffer; public: WiFiClient(); WiFiClient(int sock); - ~WiFiClient(); int connect(IPAddress ip, uint16_t port); int connect(const char *host, uint16_t port); diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiGeneric.cpp b/arduino/realtek-ambz/libraries/WiFi/WiFiGeneric.cpp index f6baad5..2576c0c 100644 --- a/arduino/realtek-ambz/libraries/WiFi/WiFiGeneric.cpp +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiGeneric.cpp @@ -16,12 +16,11 @@ bool WiFiClass::mode(WiFiMode mode) { // initialize wifi first LwIP_Init(); reset_wifi_struct(); - wifi_manager_init(); + // wifi_manager_init(); // these are events! _initialized = true; } if (currentMode) { // stop wifi to change mode - dhcps_deinit(); if (wifi_off() != RTW_SUCCESS) return false; vTaskDelay(20); @@ -29,10 +28,6 @@ bool WiFiClass::mode(WiFiMode mode) { if (wifi_on((rtw_mode_t)mode) != RTW_SUCCESS) return false; - - if (mode & WIFI_MODE_AP) { - dhcps_init(NETIF_RTW_STA); - } return true; } @@ -52,7 +47,7 @@ WiFiStatus WiFiClass::status() { bool WiFiClass::enableSTA(bool enable) { WiFiMode currentMode = getMode(); - if ((currentMode & WIFI_MODE_STA != 0) != enable) { + if (((currentMode & WIFI_MODE_STA) != 0) != enable) { return mode((WiFiMode)(currentMode ^ WIFI_MODE_STA)); } return true; @@ -60,7 +55,7 @@ bool WiFiClass::enableSTA(bool enable) { bool WiFiClass::enableAP(bool enable) { WiFiMode currentMode = getMode(); - if ((currentMode & WIFI_MODE_AP != 0) != enable) { + if (((currentMode & WIFI_MODE_AP) != 0) != enable) { return mode((WiFiMode)(currentMode ^ WIFI_MODE_AP)); } return true; diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiPriv.h b/arduino/realtek-ambz/libraries/WiFi/WiFiPriv.h index b8072aa..22b3a82 100644 --- a/arduino/realtek-ambz/libraries/WiFi/WiFiPriv.h +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiPriv.h @@ -18,6 +18,18 @@ extern "C" { #define WIFI_CLIENT_SELECT_TIMEOUT 1000 #define WIFI_CLIENT_FLUSH_BUF_SIZE 1024 +// I think I don't understand how that works. +// For some reason, LwIP uses a different (extern) errno, +// while this macro refers to a function __errno, which +// reads a totally different variable. +#undef errno +#include + +// disable #defines removing lwip_ prefix +#undef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 0 +#include + #include #include #include diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiServer.cpp b/arduino/realtek-ambz/libraries/WiFi/WiFiServer.cpp new file mode 100644 index 0000000..52f2997 --- /dev/null +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiServer.cpp @@ -0,0 +1,104 @@ +#include "WiFiServer.h" +#include "WiFiPriv.h" + +WiFiServer::WiFiServer(uint16_t port, uint8_t maxClients) + : _sock(-1), _sockAccepted(-1), _port(port), _maxClients(maxClients), _active(false), _noDelay(false) {} + +WiFiServer::operator bool() { + return _active; +} + +bool WiFiServer::begin(uint16_t port, bool reuseAddr) { + if (_active) + return true; + if (port) + _port = port; + + _sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (_sock < 0) + return false; + + int enable = reuseAddr; + lwip_setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(_port); + + if (lwip_bind(_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + return false; + + if (lwip_listen(_sock, _maxClients) < 0) + return false; + + lwip_fcntl(_sock, F_SETFL, O_NONBLOCK); + _active = true; + _noDelay = false; + _sockAccepted = -1; +} + +void WiFiServer::end() { + if (_sock == -1) + return; + lwip_close(_sock); + _sock = -1; + _active = -1; +} + +WiFiClient WiFiServer::accept() { + if (!_active) + return WiFiClient(); + + int sock; + if (_sockAccepted) { + sock = _sockAccepted; + _sockAccepted = -1; + } else { + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + sock = lwip_accept(_sock, (struct sockaddr *)&addr, &len); + } + + if (sock >= 0) { + int enable = 1; + if (lwip_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)) == ERR_OK) { + enable = _noDelay; + if (lwip_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)) == ERR_OK) { + return WiFiClient(sock); + } + } + } + + return WiFiClient(); +} + +int WiFiServer::setTimeout(uint32_t seconds) { + struct timeval tv; + tv.tv_sec = seconds; + tv.tv_usec = 0; + if (lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) + return -1; + return lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); +} + +void WiFiServer::setNoDelay(bool noDelay) { + _noDelay = noDelay; +} + +bool WiFiServer::getNoDelay() { + return _noDelay; +} + +bool WiFiServer::hasClient() { + if (_sockAccepted >= 0) { + return true; + } + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + _sockAccepted = lwip_accept(_sock, (struct sockaddr *)&addr, &len); + if (_sockAccepted >= 0) { + return true; + } + return false; +} diff --git a/arduino/realtek-ambz/libraries/WiFi/WiFiServer.h b/arduino/realtek-ambz/libraries/WiFi/WiFiServer.h new file mode 100644 index 0000000..ac353de --- /dev/null +++ b/arduino/realtek-ambz/libraries/WiFi/WiFiServer.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "WiFiClient.h" + +class WiFiServer : public IWiFiServer { + private: + int _sock; + int _sockAccepted; + uint16_t _port; + uint8_t _maxClients; + bool _active; + bool _noDelay = false; + + public: + WiFiServer(uint16_t port = 80, uint8_t maxClients = 4); + + operator bool(); + + bool begin(uint16_t port = 0, bool reuseAddr = true); + void end(); + WiFiClient accept(); + + size_t write(const uint8_t *buffer, size_t size) { + return 0; + } + + void stopAll() {} + + int setTimeout(uint32_t seconds); + void setNoDelay(bool noDelay); + bool getNoDelay(); + bool hasClient(); +}; diff --git a/builder/arduino-common.py b/builder/arduino-common.py index ae9a9f2..c2c44ae 100644 --- a/builder/arduino-common.py +++ b/builder/arduino-common.py @@ -17,6 +17,7 @@ env.Prepend( # fmt: off join(API_DIR), join(LT_API_DIR), + join(LT_API_DIR, "compat"), # fmt: on ] ) diff --git a/builder/frameworks/realtek-ambz-arduino.py b/builder/frameworks/realtek-ambz-arduino.py index d92f3ed..065b819 100644 --- a/builder/frameworks/realtek-ambz-arduino.py +++ b/builder/frameworks/realtek-ambz-arduino.py @@ -61,6 +61,7 @@ env.Append( ("bool", "bool"), # enable LwIPRxBuffer "LT_HAS_LWIP", + ("zalloc", "os_zalloc"), ], LINKFLAGS=[ "--specs=nosys.specs", @@ -170,6 +171,7 @@ sources_libs = [ "+<" + CORE_DIR +"/libraries/WiFi/WiFiClient.cpp>", "+<" + CORE_DIR +"/libraries/WiFi/WiFiGeneric.cpp>", "+<" + CORE_DIR +"/libraries/WiFi/WiFiScan.cpp>", + "+<" + CORE_DIR +"/libraries/WiFi/WiFiServer.cpp>", "+<" + CORE_DIR +"/libraries/WiFi/WiFiSTA.cpp>", # fmt: on ] diff --git a/fixups/realtek-ambz/wifi_mode.c b/fixups/realtek-ambz/wifi_mode.c index 56da3e1..5427457 100644 --- a/fixups/realtek-ambz/wifi_mode.c +++ b/fixups/realtek-ambz/wifi_mode.c @@ -1,4 +1,4 @@ #include // wifi_mode is declared in atcmd_wifi.c, which is a part of the built-in trash console -rtw_mode_t wifi_mode = RTW_MODE_STA; +rtw_mode_t wifi_mode = RTW_MODE_NONE;