diff --git a/README.md b/README.md
index 22e8478..c7d7411 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,12 @@
-
+First an important note: There are more suitable libraries for ENC28J60 with ESP8266, RP2040, ESP32 and Mbed Arduino platforms:
+
+* With ESP8266 and RP2040 platform you can use the EthernetCompat.h from the lwIP_enc28j60 bundled library.
+* With ESP32 platform version 3 you can use the [EthernetESP32](https://github.com/Networking-for-Arduino/EthernetESP32) library which integrates with networking on the ESP32 platform.
+* With Arduino Mbed Core boards you can use the [ENC28J60-EMAC](https://github.com/Networking-for-Arduino/ENC28J60-EMAC) library with the platforms Ethernet library
+
+---
+
+# EthernetENC
EthernetENC is the Ethernet library for ENC28J60. It is a modern version of [the UIPEthernet library](https://github.com/jandrassy/EthernetENC/wiki/UIPEthernet).
@@ -13,13 +21,6 @@ The modernization includes:
* has UDP backlog to receive more than one message at time
* Arduino 1.5 library format built with dot_a_linkage option for optimal build result
-
- Notes for ESP (click to expand)
-
-* *For esp8266 Arduino there is a much better option for enc28j60 than using this library. Use the lwIP_enc28j60 library bundled with esp8266 Arduino boards support package 3. (There is also a lwIP_w5500 and lwIP_w5100 library.)*
-* *For ESP32 it is better than using a MAC layer module like the enc28j60 to use a PHY layer LAN module like LAN8720 supported by the ESP32 MAC peripheral and the Arduino boards support package.*
-
-
[The documentation of Arduino Ethernet library](https://www.arduino.cc/en/Reference/Ethernet) applies for classes and functions descriptions.
Limitations:
diff --git a/library.properties b/library.properties
index b54648c..eecd621 100644
--- a/library.properties
+++ b/library.properties
@@ -3,9 +3,9 @@ author=Norbert Truchsess, Juraj Andrassy
maintainer=Juraj Andrassy
sentence=Ethernet library for ENC28J60. Only include EthernetENC.h instead of Ethernet.h
paragraph=This is a modern version of the UIPEthernet library. EthernetENC library is compatible with all Arduino architectures with Arduino SPI library with transactions support.
-url=https://github.com/jandrassy/EthernetENC/wiki
+url=https://github.com/Networking-for-Arduino/EthernetENC/wiki
architectures=*
-version=2.0.3
+version=2.0.5
category=Communication
includes=EthernetENC.h
dot_a_linkage=true
diff --git a/src/Dhcp.cpp b/src/Dhcp.cpp
index cc71c68..cfcd2f6 100644
--- a/src/Dhcp.cpp
+++ b/src/Dhcp.cpp
@@ -204,6 +204,7 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
// OPT - host name
buffer[16] = hostName;
+ if (_hostname == nullptr) {
buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
strcpy((char*)&(buffer[18]), HOST_NAME);
@@ -213,6 +214,12 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
//put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 30);
+ } else {
+ uint8_t len = strlen(_hostname);
+ buffer[17] = len;
+ _dhcpUdpSocket.write(buffer, 18);
+ _dhcpUdpSocket.write(_hostname, len);
+ }
if(messageType == DHCP_REQUEST)
{
@@ -468,6 +475,10 @@ IPAddress DhcpClass::getDnsServerIp()
return IPAddress(_dhcpDnsServerIp);
}
+void DhcpClass::setHostname(const char* hostname) {
+ _hostname = hostname;
+}
+
void DhcpClass::printByte(char * buf, uint8_t n ) {
char *str = &buf[1];
buf[0]='0';
diff --git a/src/Dhcp.h b/src/Dhcp.h
index febdd20..ec99072 100644
--- a/src/Dhcp.h
+++ b/src/Dhcp.h
@@ -141,6 +141,7 @@ class DhcpClass {
uint32_t _dhcpInitialTransactionId;
uint32_t _dhcpTransactionId;
uint8_t _dhcpMacAddr[6];
+ const char* _hostname = nullptr;
#ifdef __arm__
uint8_t _dhcpLocalIp[4] __attribute__((aligned(4)));
uint8_t _dhcpSubnetMask[4] __attribute__((aligned(4)));
@@ -181,6 +182,8 @@ class DhcpClass {
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
int checkLease();
+
+ void setHostname(const char* hostname);
};
#endif
diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp
index 919003d..df1c77f 100644
--- a/src/Ethernet.cpp
+++ b/src/Ethernet.cpp
@@ -19,6 +19,7 @@
#include
#include "Ethernet.h"
+#include "Dns.h"
#include "utility/Enc28J60Network.h"
extern "C"
@@ -40,6 +41,7 @@ IPAddress UIPEthernetClass::_dnsServerAddress;
DhcpClass* UIPEthernetClass::_dhcp(NULL);
unsigned long UIPEthernetClass::periodic_timer;
+unsigned long UIPEthernetClass::arp_timer;
// Because uIP isn't encapsulated within a class we have to use global
// variables, so we can only have one TCP/IP stack per program.
@@ -54,11 +56,21 @@ void UIPEthernetClass::init(uint8_t csPin)
}
#if UIP_UDP
+void
+UIPEthernetClass::setHostname(const char* hostname)
+{
+ if (_dhcp == NULL) {
+ _dhcp = new DhcpClass();
+ }
+ _dhcp->setHostname(hostname);
+}
+
int
UIPEthernetClass::begin(const uint8_t* mac, unsigned long timeout, unsigned long responseTimeout)
{
- static DhcpClass s_dhcp;
- _dhcp = &s_dhcp;
+ if (_dhcp == NULL) {
+ _dhcp = new DhcpClass();
+ }
// Initialise the basic info
init(mac);
@@ -105,7 +117,29 @@ UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddre
configure(ip,dns,gateway,subnet);
}
+void UIPEthernetClass::end()
+{
+ //close all clients
+ for (int i = 0; i < UIP_CONNS; i++)
+ {
+ if (EthernetClient::all_data[i].state) {
+ EthernetClient client(&EthernetClient::all_data[i]);
+ client.stop();
+ }
+ }
+ // handle clients closings
+ uint32_t st = millis();
+ while (millis() - st < 3000)
+ {
+ tick();
+ }
+ initialized = false;
+ configure(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
+}
+
int UIPEthernetClass::maintain(){
+ if (!initialized)
+ return 0;
tick();
int rc = DHCP_CHECK_NONE;
#if UIP_UDP
@@ -144,6 +178,12 @@ EthernetHardwareStatus UIPEthernetClass::hardwareStatus()
return EthernetENC28J60;
}
+uint8_t* UIPEthernetClass::macAddress(uint8_t* mac)
+{
+ memcpy(mac, uip_ethaddr.addr, 6);
+ return mac;
+}
+
IPAddress UIPEthernetClass::localIP()
{
IPAddress ret;
@@ -173,11 +213,34 @@ IPAddress UIPEthernetClass::dnsServerIP()
return _dnsServerAddress;
}
+IPAddress UIPEthernetClass::dnsIP(int n) {
+ return (n == 0) ? _dnsServerAddress : IPAddress();
+}
+
+int UIPEthernetClass::hostByName(const char* hostname, IPAddress& result)
+{
+ // Look up the host first
+ int ret = 0;
+#if UIP_UDP
+ DNSClient dns;
+ dns.begin(_dnsServerAddress);
+ ret = dns.getHostByName(hostname, result);
+#endif
+ return ret;
+}
+
void
UIPEthernetClass::tick()
{
if (!initialized)
return;
+
+ // run ARP table cleanup every 10 seconds as required by a comment in uip_arp.h
+ if (millis() - arp_timer > 10000) {
+ arp_timer = millis();
+ uip_arp_timer();
+ }
+
if (in_packet == NOBLOCK)
{
in_packet = Enc28J60Network::receivePacket();
@@ -488,3 +551,9 @@ uip_udpchksum(void)
#endif
UIPEthernetClass Ethernet;
+
+extern "C" void serialPrint(int i);
+void serialPrint(int i) {
+ Serial.println(i);
+ Serial.flush();
+}
diff --git a/src/Ethernet.h b/src/Ethernet.h
index 62d2c35..3f9ddbf 100644
--- a/src/Ethernet.h
+++ b/src/Ethernet.h
@@ -85,6 +85,8 @@ class UIPEthernetClass
void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway);
void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
+ void end();
+
// maintain() must be called at regular intervals to process the incoming serial
// data and issue IP events to the sketch. It does not return until all IP
// events have been processed. Renews dhcp-lease if required.
@@ -92,11 +94,22 @@ class UIPEthernetClass
EthernetLinkStatus linkStatus();
EthernetHardwareStatus hardwareStatus();
+
+ uint8_t* macAddress(uint8_t* mac);
+ void MACAddress(uint8_t *mac_address) { macAddress(mac_address); }
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsServerIP();
+ IPAddress dnsIP(int n = 0);
+
+ void setDnsServerIP(const IPAddress dns_server) { _dnsServerAddress = dns_server; }
+ void setDNS(IPAddress dns_server) { _dnsServerAddress = dns_server; }
+
+ void setHostname(const char* hostname); // only the pointer is stored!
+
+ int hostByName(const char* hostname, IPAddress& result);
private:
static bool initialized;
@@ -109,6 +122,7 @@ class UIPEthernetClass
static DhcpClass* _dhcp;
static unsigned long periodic_timer;
+ static unsigned long arp_timer;
static void init(const uint8_t* mac);
static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp
index 0e75552..636bc1d 100644
--- a/src/EthernetClient.cpp
+++ b/src/EthernetClient.cpp
@@ -25,7 +25,6 @@ extern "C"
}
#include "Ethernet.h"
#include "EthernetClient.h"
-#include "Dns.h"
#define UIP_TCP_PHYH_LEN UIP_LLH_LEN+UIP_IPTCPH_LEN
@@ -53,7 +52,7 @@ UIPClient::connect(IPAddress ip, uint16_t port)
if (conn)
{
#if UIP_CONNECT_TIMEOUT > 0
- uint32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT;
+ uint32_t timeout = millis() + connectTimeout;
#endif
while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
{
@@ -87,11 +86,8 @@ UIPClient::connect(const char *host, uint16_t port)
// Look up the host first
int ret = 0;
#if UIP_UDP
- DNSClient dns;
IPAddress remote_addr;
-
- dns.begin(UIPEthernetClass::_dnsServerAddress);
- ret = dns.getHostByName(host, remote_addr);
+ ret = Ethernet.hostByName(host, remote_addr);
if (ret == 1) {
return connect(remote_addr, port);
}
@@ -369,7 +365,13 @@ uint16_t
UIPClient::remotePort(void)
{
return data ? ntohs(uip_conns[data->conn_index].rport) : 0;
-}
+}
+
+uint8_t
+UIPClient::status()
+{
+ return !data ? UIP_CLOSED : uip_conns[data->conn_index].tcpstateflags & UIP_TS_MASK;
+}
void
uipclient_appcall(void)
@@ -532,9 +534,9 @@ UIPClient::_allocateData()
uip_userdata_t* data = &UIPClient::all_data[sock];
if (!data->state)
{
- memset(data, 0, sizeof(uip_userdata_t));
- data->conn_index = uip_conn - uip_conns; // pointer arithmetics
- data->state = UIP_CLIENT_CONNECTED;
+ *data = uip_userdata_t();
+ data->conn_index = uip_conn - uip_conns; // pointer arithmetics
+ data->state = UIP_CLIENT_CONNECTED;
return data;
}
}
diff --git a/src/EthernetClient.h b/src/EthernetClient.h
index d78c769..8807ece 100644
--- a/src/EthernetClient.h
+++ b/src/EthernetClient.h
@@ -77,12 +77,17 @@ class EthernetClient : public Client {
IPAddress remoteIP();
uint16_t remotePort();
+
+ uint8_t status();
+
+ void setConnectionTimeout(uint16_t millis) {connectTimeout = millis;}
private:
EthernetClient(struct uip_conn *_conn);
EthernetClient(uip_userdata_t* conn_data);
uip_userdata_t* data;
+ uint16_t connectTimeout = 1000 * UIP_CONNECT_TIMEOUT;
static uip_userdata_t all_data[UIP_CONNS];
static uip_userdata_t* _allocateData();
diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp
index 4a51a4f..9237ad9 100644
--- a/src/EthernetServer.cpp
+++ b/src/EthernetServer.cpp
@@ -64,6 +64,12 @@ void UIPServer::begin()
listening = true;
}
+void UIPServer::begin(uint16_t port)
+{
+ _port = port;
+ begin();
+}
+
void UIPServer::end() {
uip_unlisten(_port);
listening = false;
diff --git a/src/EthernetServer.h b/src/EthernetServer.h
index 1dae460..fec7006 100644
--- a/src/EthernetServer.h
+++ b/src/EthernetServer.h
@@ -24,10 +24,11 @@
class EthernetServer {
public:
- EthernetServer(uint16_t);
+ EthernetServer(uint16_t port = 80);
EthernetClient available();
EthernetClient accept();
void begin();
+ void begin(uint16_t port);
void end();
operator bool();
@@ -42,7 +43,7 @@ class EthernetServer {
class EthernetServerPrint : public EthernetServer, public Print {
public:
- EthernetServerPrint(uint16_t port) : EthernetServer(port) {}
+ EthernetServerPrint(uint16_t port = 80) : EthernetServer(port) {}
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp
index e3d7cd1..979037b 100644
--- a/src/EthernetUdp.cpp
+++ b/src/EthernetUdp.cpp
@@ -19,7 +19,6 @@
#include "Ethernet.h"
#include "EthernetUdp.h"
-#include "Dns.h"
extern "C" {
#include "utility/uip-conf.h"
@@ -35,9 +34,9 @@ extern "C" {
// Constructor
UIPUDP::UIPUDP() :
- _uip_udp_conn(NULL)
+ _uip_udp_conn(NULL),
+ appdata()
{
- memset(&appdata,0,sizeof(appdata));
}
// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
@@ -69,7 +68,7 @@ UIPUDP::stop()
Enc28J60Network::freeBlock(appdata.packet_in);
_flushBlocks(appdata.packet_next);
Enc28J60Network::freeBlock(appdata.packet_out);
- memset(&appdata,0,sizeof(appdata));
+ appdata = uip_udp_userdata_t();
}
}
@@ -149,11 +148,8 @@ UIPUDP::beginPacket(const char *host, uint16_t port)
{
// Look up the host first
int ret = 0;
- DNSClient dns;
IPAddress remote_addr;
-
- dns.begin(Ethernet.dnsServerIP());
- ret = dns.getHostByName(host, remote_addr);
+ ret = Ethernet.hostByName(host, remote_addr);
if (ret == 1) {
return beginPacket(remote_addr, port);
} else {
diff --git a/src/tcp_states.h b/src/tcp_states.h
new file mode 100644
index 0000000..02864da
--- /dev/null
+++ b/src/tcp_states.h
@@ -0,0 +1,21 @@
+
+#ifndef UIP_TCP_STATES_H
+#define UIP_TCP_STATES_H
+
+#include
+
+// common constants for client.state() return values
+enum uip_tcp_state {
+ CLOSED = UIP_CLOSED,
+ SYN_SENT = UIP_SYN_SENT,
+ SYN_RCVD = UIP_SYN_RCVD,
+ ESTABLISHED = UIP_ESTABLISHED,
+ FIN_WAIT_1 = UIP_FIN_WAIT_1,
+ FIN_WAIT_2 = UIP_FIN_WAIT_2,
+ CLOSE_WAIT = 10, // not used
+ CLOSING = UIP_CLOSING,
+ LAST_ACK = UIP_LAST_ACK,
+ TIME_WAIT = UIP_TIME_WAIT
+};
+
+#endif
diff --git a/src/utility/uip_arp.c b/src/utility/uip_arp.c
index 44ca7c4..86b4df8 100644
--- a/src/utility/uip_arp.c
+++ b/src/utility/uip_arp.c
@@ -170,8 +170,7 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
/* Check if the source IP address of the incoming packet matches
the IP address in this ARP table entry. */
- if(ipaddr[0] == tabptr->ipaddr[0] &&
- ipaddr[1] == tabptr->ipaddr[1]) {
+ if(memcmp(ipaddr, tabptr->ipaddr, 4) == 0) {
/* An old entry found, update this and return. */
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);