diff --git a/cores/esp8266/LwipIntfDev.h b/cores/esp8266/LwipIntfDev.h index 00f29e9dfe..389376c976 100644 --- a/cores/esp8266/LwipIntfDev.h +++ b/cores/esp8266/LwipIntfDev.h @@ -46,6 +46,13 @@ #define DEFAULT_MTU 1500 #endif +enum EthernetLinkStatus +{ + Unknown, + LinkON, + LinkOFF +}; + template class LwipIntfDev: public LwipIntf, public RawDev { @@ -93,9 +100,11 @@ class LwipIntfDev: public LwipIntf, public RawDev void setDefault(bool deflt = true); // true if interface has a valid IPv4 address + // (and ethernet link status is not detectable or is up) bool connected() { - return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)); + return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)) + && (!RawDev::isLinkDetectable() || RawDev::isLinked()); } bool routable() @@ -106,6 +115,9 @@ class LwipIntfDev: public LwipIntf, public RawDev // ESP8266WiFi API compatibility wl_status_t status(); + // Arduino Ethernet compatibility + EthernetLinkStatus linkStatus(); + protected: err_t netif_init(); void check_route(); @@ -282,6 +294,12 @@ wl_status_t LwipIntfDev::status() return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD; } +template +EthernetLinkStatus LwipIntfDev::linkStatus() +{ + return RawDev::isLinkDetectable() ? _started && RawDev::isLinked() ? LinkON : LinkOFF : Unknown; +} + template err_t LwipIntfDev::linkoutput_s(netif* netif, struct pbuf* pbuf) { diff --git a/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino b/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino index 8ca28fa112..169930f6ef 100644 --- a/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino +++ b/libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino @@ -52,6 +52,8 @@ void loop() { Serial.print(':'); Serial.println(port); + Serial.printf("Link sense: %d (detectable: %d)\n", eth.isLinked(), eth.isLinkDetectable()); + // Use WiFiClient class to create TCP connections // (this class could have been named TCPClient) WiFiClient client; diff --git a/libraries/lwIP_Ethernet/src/EthernetCompat.h b/libraries/lwIP_Ethernet/src/EthernetCompat.h index e398d5719d..99dca03e67 100644 --- a/libraries/lwIP_Ethernet/src/EthernetCompat.h +++ b/libraries/lwIP_Ethernet/src/EthernetCompat.h @@ -10,13 +10,6 @@ using EthernetUDP = WiFiUDP; using EthernetClient = WiFiClient; using EthernetServer = ArduinoWiFiServer; -enum EthernetLinkStatus -{ - Unknown, - LinkON, - LinkOFF -}; - enum { DHCP_CHECK_NONE = 0, @@ -40,7 +33,6 @@ class ArduinoEthernet: public LwipIntfDev LwipIntfDev(cs, spi, intr) { _hardwareStatus = EthernetNoHardware; - _linkStatus = Unknown; } // Arduino-Ethernet API compatibility, order can be either: @@ -70,7 +62,6 @@ class ArduinoEthernet: public LwipIntfDev if (ret) { _hardwareStatus = EthernetHardwareFound; - _linkStatus = LinkON; } return ret; @@ -81,19 +72,13 @@ class ArduinoEthernet: public LwipIntfDev return _hardwareStatus; } - EthernetLinkStatus linkStatus() const - { - return _linkStatus; - } - int maintain() const { return DHCP_CHECK_NONE; } protected: - HardwareStatus _hardwareStatus; - EthernetLinkStatus _linkStatus; + HardwareStatus _hardwareStatus; }; using ArduinoWiznet5500lwIP = ArduinoEthernet; diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp b/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp index 979d88e9ea..09f8ae0fe2 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.cpp @@ -106,6 +106,7 @@ void serial_printf(const char* fmt, ...) #define MACONX_BANK 0x02 #define MACON1 0x00 +#define MACSTAT1 0x01 #define MACON3 0x02 #define MACON4 0x03 #define MABBIPG 0x04 @@ -113,6 +114,16 @@ void serial_printf(const char* fmt, ...) #define MAIPGH 0x07 #define MAMXFLL 0x0a #define MAMXFLH 0x0b +#define MACON2 0x10 +#define MACSTAT2 0x11 +#define MICMD 0x12 +#define MIREGADR 0x14 +#define MIRDL 0x18 +#define MIRDH 0x19 + +/* MICMD Register Bit Definitions */ +#define MICMD_MIISCAN 0x02 +#define MICMD_MIIRD 0x01 #define MACON1_TXPAUS 0x08 #define MACON1_RXPAUS 0x04 @@ -135,6 +146,9 @@ void serial_printf(const char* fmt, ...) #define MISTAT 0x0a #define EREVID 0x12 +/* MISTAT Register Bit Definitions */ +#define MISTAT_BUSY 0x01 + #define EPKTCNT_BANK 0x01 #define ERXFCON 0x18 #define EPKTCNT 0x19 @@ -720,3 +734,26 @@ uint16_t ENC28J60::readFrameData(uint8_t* buffer, uint16_t framesize) return _len; } + +uint16_t ENC28J60::phyread(uint8_t reg) +{ + // ( https://github.com/JAndrassy/EthernetENC/tree/master/src/utility/enc28j60.h ) + + setregbank(MACONX_BANK); + writereg(MIREGADR, reg); + writereg(MICMD, MICMD_MIIRD); + // wait until the PHY read completes + while (readreg(MISTAT) & MISTAT_BUSY) + { + delayMicroseconds(15); + } + writereg(MICMD, 0); + return (readreg(MIRDL) | readreg(MIRDH) << 8); +} + +bool ENC28J60::isLinked() +{ + // ( https://github.com/JAndrassy/EthernetENC/tree/master/src/utility/enc28j60.h ) + + return !!(phyread(MACSTAT2) & 0x400); +} diff --git a/libraries/lwIP_enc28j60/src/utility/enc28j60.h b/libraries/lwIP_enc28j60/src/utility/enc28j60.h index 07f71f96ff..e6c65d7759 100644 --- a/libraries/lwIP_enc28j60/src/utility/enc28j60.h +++ b/libraries/lwIP_enc28j60/src/utility/enc28j60.h @@ -79,6 +79,21 @@ class ENC28J60 */ virtual uint16_t readFrame(uint8_t* buffer, uint16_t bufsize); + /** + Check physical link + @return true when physical link is up + */ + bool isLinked(); + + /** + Report whether ::isLinked() API is implemented + @return true when ::isLinked() API is implemented + */ + constexpr bool isLinkDetectable() const + { + return true; + } + protected: static constexpr bool interruptIsPossible() { @@ -133,6 +148,8 @@ class ENC28J60 // Previously defined in contiki/core/sys/clock.h void clock_delay_usec(uint16_t dt); + uint16_t phyread(uint8_t reg); + uint8_t _bank; int8_t _cs; SPIClass& _spi; diff --git a/libraries/lwIP_w5100/src/utility/w5100.h b/libraries/lwIP_w5100/src/utility/w5100.h index 6e1f2c35cd..9ed1e4cdab 100644 --- a/libraries/lwIP_w5100/src/utility/w5100.h +++ b/libraries/lwIP_w5100/src/utility/w5100.h @@ -79,6 +79,24 @@ class Wiznet5100 */ uint16_t readFrame(uint8_t* buffer, uint16_t bufsize); + /** + Check physical link + @return true when physical link is up + */ + bool isLinked() const + { + return true; //XXX TODO + } + + /** + Report whether ::isLinked() API is implemented + @return true when ::isLinked() API is implemented + */ + constexpr bool isLinkDetectable() const + { + return false; + } + protected: static constexpr bool interruptIsPossible() { diff --git a/libraries/lwIP_w5500/src/utility/w5500.h b/libraries/lwIP_w5500/src/utility/w5500.h index f7babb51e9..7e8058fdb1 100644 --- a/libraries/lwIP_w5500/src/utility/w5500.h +++ b/libraries/lwIP_w5500/src/utility/w5500.h @@ -79,6 +79,24 @@ class Wiznet5500 */ uint16_t readFrame(uint8_t* buffer, uint16_t bufsize); + /** + Check physical link + @return true when physical link is up + */ + bool isLinked() + { + return wizphy_getphylink() == PHY_LINK_ON; + } + + /** + Report whether ::isLinked() API is implemented + @return true when ::isLinked() API is implemented + */ + constexpr bool isLinkDetectable() const + { + return true; + } + protected: static constexpr bool interruptIsPossible() {