From 4f347d7a84031d6a2844511ac102f018ce4744ac Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 26 Dec 2020 11:45:04 +0100 Subject: [PATCH 01/16] Update w5100.h --- src/utility/w5100.h | 61 +++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/src/utility/w5100.h b/src/utility/w5100.h index 099556a6..c7e097ba 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -49,6 +49,13 @@ #endif +// Industruino D21G can't use W5500 faster than 4 MHz +#if defined(INDIO_H_) +#undef SPI_ETHERNET_SETTINGS +#define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) +#endif + + typedef uint8_t SOCKET; class SnMR { @@ -140,8 +147,9 @@ class W5100Class { inline void setIPAddress(const uint8_t * addr) { writeSIPR(addr); } inline void getIPAddress(uint8_t * addr) { readSIPR(addr); } - inline void setRetransmissionTime(uint16_t timeout) { writeRTR(timeout); } - inline void setRetransmissionCount(uint8_t retry) { writeRCR(retry); } + inline void setRetransmissionTime(uint16_t timeout) { if (chip == 55) writeRTR_W5500(timeout); else writeRTR_W5100(timeout); } + inline void setRetransmissionCount(uint8_t retry) { if (chip == 55) writeRCR_W5500(retry); else writeRCR_W5100(retry); } + static void execCmdSn(SOCKET s, SockCMD _cmd); @@ -190,26 +198,35 @@ class W5100Class { static W5100Linkstatus getLinkStatus(); public: - __GP_REGISTER8 (MR, 0x0000); // Mode - __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address - __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address - __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address - __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address - __GP_REGISTER8 (IR, 0x0015); // Interrupt - __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask - __GP_REGISTER16(RTR, 0x0017); // Timeout address - __GP_REGISTER8 (RCR, 0x0019); // Retry count - __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size (W5100 only) - __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size (W5100 only) - __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode - __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer - __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number - __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode (W5100 only) - __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode (W5100 only) - __GP_REGISTER8 (VERSIONR_W5200,0x001F); // Chip Version Register (W5200 only) - __GP_REGISTER8 (VERSIONR_W5500,0x0039); // Chip Version Register (W5500 only) - __GP_REGISTER8 (PSTATUS_W5200, 0x0035); // PHY Status - __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default: 10111xxx + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR_W5100, 0x0017); // Timeout address + __GP_REGISTER16(RTR_W5500, 0x0019); // Timeout address (W5500 only) + __GP_REGISTER8 (RCR_W5100, 0x0019); // Retry count + __GP_REGISTER8 (RCR_W5500, 0x001B); // Retry count (W5500 only) + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size (W5100 only) + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size (W5100 only) + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER_W5100, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PTIMER_W5500, 0x001C); // PPP LCP Request Timer (W5500 only) + __GP_REGISTER8 (PMAGIC_W5100, 0x0029); // PPP LCP Magic Number + __GP_REGISTER8 (PMAGIC_W5500, 0x001D); // PPP LCP Magic Number (W5500 only) + __GP_REGISTER_N(UIPR_W5100, 0x002A, 4); // Unreachable IP address in UDP mode (W5100 only) + __GP_REGISTER_N(UIPR_W5500, 0x0028, 4); // Unreachable IP address in UDP mode (W5500 only) + __GP_REGISTER16(UPORT_W5100, 0x002E); // Unreachable Port address in UDP mode (W5100 only) + __GP_REGISTER16(UPORT_W5500, 0x002C); // Unreachable Port address in UDP mode (W5500 only) + __GP_REGISTER8 (VERSIONR_W5200,0x001F); // Chip Version Register (W5200 only) + __GP_REGISTER8 (VERSIONR_W5500,0x0039); // Chip Version Register (W5500 only) + __GP_REGISTER8 (PSTATUS_W5200, 0x0035); // PHY Status + __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default: 10111xxx + __GP_REGISTER_N(PHAR, 0x001E, 6); // PPP Destination MAC address + __GP_REGISTER16(PSID, 0x0024); // PPP Session ID + __GP_REGISTER16(PMRU, 0x0026); // PPP Maximum Segment Size #undef __GP_REGISTER8 From 84c3ceac3be0372d9a17e570d20c4eebbcb42811 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Wed, 30 Dec 2020 00:28:08 +0100 Subject: [PATCH 02/16] Update w5100.h Addedd last few missing registers for W5500 --- src/utility/w5100.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/utility/w5100.h b/src/utility/w5100.h index c7e097ba..a262d088 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -203,9 +203,12 @@ class W5100Class { __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER16(INTLEVEL, 0x0013); // Interrupt Low Level Timer __GP_REGISTER8 (IR, 0x0015); // Interrupt __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER8 (SIR, 0x0017); // Socket Interrupt (W5500 only) __GP_REGISTER16(RTR_W5100, 0x0017); // Timeout address + __GP_REGISTER8 (SIMR, 0x0018); // Socket Interrupt Mask __GP_REGISTER16(RTR_W5500, 0x0019); // Timeout address (W5500 only) __GP_REGISTER8 (RCR_W5100, 0x0019); // Retry count __GP_REGISTER8 (RCR_W5500, 0x001B); // Retry count (W5500 only) @@ -306,6 +309,9 @@ class W5100Class { __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + __SOCKET_REGISTER8(Sn_IMR, 0x002C) // Interrupt Mask (W5500 only) + __SOCKET_REGISTER16(SnFRAG, 0x002D) // Fragment Offset in IP header (W5500 only) + __SOCKET_REGISTER8(Sn_KPALVTR, 0x002F) // Keep alive timer (W5500 only) #undef __SOCKET_REGISTER8 #undef __SOCKET_REGISTER16 From 2ffe2cc46c10b55e4b520aacd9514a311a530bb9 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 20 Feb 2021 13:31:10 +0100 Subject: [PATCH 03/16] Included ICMP libraries Merged the ethernet library with the ICMPPing library --- src/Ethernet.cpp | 13 +- src/Ethernet.h | 1 + src/EthernetICMP.cpp | 304 ++++++++++++++++++++++++++++++++++++++ src/EthernetICMP.h | 332 ++++++++++++++++++++++++++++++++++++++++++ src/socket.cpp | 114 +++++++++++++++ src/util.h | 14 ++ src/utility/w5100.cpp | 25 ++-- src/utility/w5100.h | 27 +--- 8 files changed, 791 insertions(+), 39 deletions(-) create mode 100644 src/EthernetICMP.cpp create mode 100644 src/EthernetICMP.h create mode 100644 src/util.h diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 9257090c..0e30eaa6 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -28,9 +28,9 @@ DhcpClass* EthernetClass::_dhcp = NULL; int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { + //SerialUSB.println("0"); static DhcpClass s_dhcp; _dhcp = &s_dhcp; - // Initialise the basic info if (W5100.init() == 0) return 0; SPI.beginTransaction(SPI_ETHERNET_SETTINGS); @@ -56,6 +56,7 @@ int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long resp void EthernetClass::begin(uint8_t *mac, IPAddress ip) { + //SerialUSB.println("1"); // Assume the DNS server will be the machine on the same network as the local IP // but with last octet being '1' IPAddress dns = ip; @@ -65,6 +66,7 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip) void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) { + //SerialUSB.println("2"); // Assume the gateway will be the machine on the same network as the local IP // but with last octet being '1' IPAddress gateway = ip; @@ -74,20 +76,19 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { + //SerialUSB.println("3"); IPAddress subnet(255, 255, 255, 0); begin(mac, ip, dns, gateway, subnet); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + //SerialUSB.println("4"); if (W5100.init() == 0) return; + //SerialUSB.println("5"); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setMACAddress(mac); -#ifdef ESP8266 - W5100.setIPAddress(&ip[0]); - W5100.setGatewayIp(&gateway[0]); - W5100.setSubnetMask(&subnet[0]); -#elif ARDUINO > 106 || TEENSYDUINO > 121 +#if ARDUINO > 106 || TEENSYDUINO > 121 W5100.setIPAddress(ip._address.bytes); W5100.setGatewayIp(gateway._address.bytes); W5100.setSubnetMask(subnet._address.bytes); diff --git a/src/Ethernet.h b/src/Ethernet.h index 376e6c59..ee8cda20 100644 --- a/src/Ethernet.h +++ b/src/Ethernet.h @@ -108,6 +108,7 @@ class EthernetClass { friend class EthernetClient; friend class EthernetServer; friend class EthernetUDP; + friend class EthernetICMP; private: // Opens a socket(TCP or UDP or IP_RAW mode) static uint8_t socketBegin(uint8_t protocol, uint16_t port); diff --git a/src/EthernetICMP.cpp b/src/EthernetICMP.cpp new file mode 100644 index 00000000..d500e2d6 --- /dev/null +++ b/src/EthernetICMP.cpp @@ -0,0 +1,304 @@ +/* + * Icmp.cpp: Library to send/receive ICMP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.cpp + * Drop Icmp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +/* + * Copyright (c) 2010 by Blake Foster + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + + +#include +//#include "Ethernet.h" +//#include "utility/w5100.h" +#include "EthernetICMP.h" + +#ifdef ICMPPING_INSERT_YIELDS +#define ICMPPING_DOYIELD() delay(2) +#else +#define ICMPPING_DOYIELD() +#endif + +inline uint16_t _makeUint16(const uint8_t& highOrder, const uint8_t& lowOrder) +{ + // make a 16-bit unsigned integer given the low order and high order bytes. + // lowOrder first because the Arduino is little endian. + uint8_t value [] = {lowOrder, highOrder}; + return *(uint16_t *)&value; +} + +uint16_t _checksum(const EthernetICMPEcho& echo) +{ + // calculate the checksum of an ICMPEcho with all fields but icmpHeader.checksum populated + unsigned long sum = 0; + + // add the header, bytes reversed since we're using little-endian arithmetic. + sum += _makeUint16(echo.icmpHeader.type, echo.icmpHeader.code); + + // add id and sequence + sum += echo.id + echo.seq; + + // add time, one half at a time. + uint16_t const * time = (uint16_t const *)&echo.time; + sum += *time + *(time + 1); + + // add the payload + for (uint8_t const * b = echo.payload; b < echo.payload + sizeof(echo.payload); b+=2) + { + sum += _makeUint16(*b, *(b + 1)); + } + + // ones complement of ones complement sum + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return ~sum; +} + +EthernetICMPEcho::EthernetICMPEcho(uint8_t type, uint16_t _id, uint16_t _seq, uint8_t * _payload) +: seq(_seq), id(_id), time(millis()) +{ + memcpy(payload, _payload, REQ_DATASIZE); + icmpHeader.type = type; + icmpHeader.code = 0; + icmpHeader.checksum = _checksum(*this); +} + +EthernetICMPEcho::EthernetICMPEcho() +: seq(0), id(0), time(0) +{ + memset(payload, 0, sizeof(payload)); + icmpHeader.code = 0; + icmpHeader.type = 0; + icmpHeader.checksum = 0; +} + +void EthernetICMPEcho::serialize(uint8_t * binData) const +{ + *(binData++) = icmpHeader.type; + *(binData++) = icmpHeader.code; + + *(uint16_t *)binData = htons(icmpHeader.checksum); binData += 2; + *(uint16_t *)binData = htons(id); binData += 2; + *(uint16_t *)binData = htons(seq); binData += 2; + *(icmp_time_t *) binData = htonl(time); binData += 4; + + memcpy(binData, payload, sizeof(payload)); +} + +void EthernetICMPEcho::deserialize(uint8_t const * binData) +{ + icmpHeader.type = *(binData++); + icmpHeader.code = *(binData++); + + icmpHeader.checksum = ntohs(*(uint16_t *)binData); binData += 2; + id = ntohs(*(uint16_t *)binData); binData += 2; + seq = ntohs(*(uint16_t *)binData); binData += 2; + + if (icmpHeader.type != TIME_EXCEEDED) + { + time = ntohl(*(icmp_time_t *)binData); binData += 4; + } + + memcpy(payload, binData, sizeof(payload)); +} + + +uint16_t EthernetICMPPing::ping_timeout = PING_TIMEOUT; + +EthernetICMPPing::EthernetICMPPing(SOCKET socket, uint8_t id) : +#ifdef ICMPPING_ASYNCH_ENABLE + _curSeq(0), _numRetries(0), _asyncstart(0), _asyncstatus(BAD_RESPONSE), +#endif + _id(id), _nextSeq(0), _socket(socket), _attempt(0) +{ + memset(_payload, 0x1A, REQ_DATASIZE); +} + + +void EthernetICMPPing::setPayload(uint8_t * payload) +{ + memcpy(_payload, payload, REQ_DATASIZE); +} + +void EthernetICMPPing::openSocket() +{ + + W5100.execCmdSn(_socket, Sock_CLOSE); + W5100.writeSnIR(_socket, 0xFF); + W5100.writeSnMR(_socket, SnMR::IPRAW); + W5100.writeSnPROTO(_socket, IPPROTO::ICMP); + W5100.writeSnPORT(_socket, 0); + W5100.execCmdSn(_socket, Sock_OPEN); +} + + + +void EthernetICMPPing::operator()(const IPAddress& addr, int nRetries, EthernetICMPEchoReply& result) +{ + openSocket(); + + EthernetICMPEcho echoReq(ICMP_ECHOREQ, _id, _nextSeq++, _payload); + + for (_attempt=0; _attempt ping_timeout) + { + + // yep, we've timed out... + if (_attempt < _numRetries) + { + // still, this wasn't our last attempt, let's try again + if (asyncSend(result)) + { + // another send has succeeded + // we'll wait for that now... + return false; + } + + // this send has failed. too bad, + // we are done. + return true; + } + + // we timed out and have no more attempts left... + // hello? is anybody out there? + // guess not: + result.status = NO_RESPONSE; + return true; + } + + // have yet to time out, will wait some more: + return false; // results still not in + +} + +#endif /* ICMPPING_ASYNCH_ENABLE */ \ No newline at end of file diff --git a/src/EthernetICMP.h b/src/EthernetICMP.h new file mode 100644 index 00000000..e1e69e72 --- /dev/null +++ b/src/EthernetICMP.h @@ -0,0 +1,332 @@ +/* + * Icmp.cpp: Library to send/receive ICMP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.cpp + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#ifndef EthernetICMP_h +#define EthernetICMP_h + +#include +#include "utility/w5100.h" + + + +/* + * Copyright (c) 2010 by Blake Foster + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + + +#define REQ_DATASIZE 64 +#define ICMP_ECHOREPLY 0 +#define ICMP_ECHOREQ 8 +#define ICMP_ECHOREP 0 +#define TIME_EXCEEDED 11 +#define PING_TIMEOUT 1000 + + +// ICMPPING_ASYNCH_ENABLE -- define this to enable asynch operations +// #define ICMPPING_ASYNCH_ENABLE + +// ICMPPING_INSERT_YIELDS -- some platforms, such as ESP8266, like +// (read: need) to do background work so control must be yielded +// back to the main system periodically when you are doing something +// that takes a good while. +// Define (uncomment the following line) on these platforms, which +// will call a short delay() at critical junctures. +// #define ICMPPING_INSERT_YIELDS + +typedef unsigned long icmp_time_t; + +class EthernetICMPHeader; +class EthernetICMPPing; + +typedef enum Status +{ + /* + Indicates whether a ping succeeded or failed due to one of various error + conditions. These correspond to error conditions that occur in this + library, not anything defined in the ICMP protocol. + */ + SUCCESS = 0, + SEND_TIMEOUT = 1, // Timed out sending the request + NO_RESPONSE = 2, // Died waiting for a response + BAD_RESPONSE = 3, // we got back the wrong type + ASYNC_SENT = 4 +} Status; + + +struct EthernetICMPHeader +{ + /* + Header for an ICMP packet. Does not include the IP header. + */ + uint8_t type; + uint8_t code; + uint16_t checksum; +}; + + +struct EthernetICMPEcho +{ + /* + Contents of an ICMP echo packet, including the ICMP header. Does not + include the IP header. + */ + + /* + This constructor sets all fields and calculates the checksum. It is used + to create ICMP packet data when we send a request. + @param type: ICMP_ECHOREQ or ICMP_ECHOREP. + @param _id: Some arbitrary id. Usually set once per process. + @param _seq: The sequence number. Usually started at zero and incremented + once per request. + @param payload: An arbitrary chunk of data that we expect to get back in + the response. + */ + EthernetICMPEcho(uint8_t type, uint16_t _id, uint16_t _seq, uint8_t * _payload); + + /* + This constructor leaves everything zero. This is used when we receive a + response, since we nuke whatever is here already when we copy the packet + data out of the W5100. + */ + EthernetICMPEcho(); + + EthernetICMPHeader icmpHeader; + uint16_t id; + uint16_t seq; + icmp_time_t time; + uint8_t payload [REQ_DATASIZE]; + + /* + Serialize the header as a byte array, in big endian format. + */ + void serialize(byte * binData) const; + /* + Serialize the header as a byte array, in big endian format. + */ + void deserialize(byte const * binData); +}; + + +struct EthernetICMPEchoReply +{ + /* + Struct returned by ICMPPing(). + @param data: The packet data, including the ICMP header. + @param ttl: Time to live + @param status: SUCCESS if the ping succeeded. One of various error codes + if it failed. + @param addr: The ip address that we received the response from. Something + is borked if this doesn't match the IP address we pinged. + */ + EthernetICMPEcho data; + uint8_t ttl; + Status status; + IPAddress addr; +}; + + +class EthernetICMPPing +{ + /* + Function-object for sending ICMP ping requests. + */ + +public: + /* + Construct an ICMP ping object. + @param socket: The socket number in the W5100. + @param id: The id to put in the ping packets. Can be pretty much any + arbitrary number. + */ + EthernetICMPPing(SOCKET s, uint8_t id); + + + /* + Control the ping timeout (ms). Defaults to PING_TIMEOUT (1000ms) but can + be set using setTimeout(MS). + @param timeout_ms: Timeout for ping replies, in milliseconds. + @note: this value is static -- i.e. system-wide for all ICMPPing objects. + */ + static void setTimeout(uint16_t setTo) { ping_timeout = setTo;} + + /* + Fetch the current setting for ping timeouts (in ms). + @return: timeout for all ICMPPing requests, in milliseconds. + */ + static uint16_t timeout() { return ping_timeout;} + + + /* + Pings the given IP address. + @param addr: IP address to ping, as an array of four octets. + @param nRetries: Number of times to rety before giving up. + @return: An ICMPEchoReply containing the response. The status field in + the return value indicates whether the echo request succeeded or + failed. If the request failed, the status indicates the reason for + failure on the last retry. + */ + EthernetICMPEchoReply operator()(const IPAddress&, int nRetries); + + /* + This overloaded version of the () operator takes a (hopefully blank) + ICMPEchoReply as parameter instead of constructing one internally and + then copying it on return. This creates a very small improvement in + efficiency at the cost of making your code uglier. + @param addr: IP address to ping, as an array of four octets. + @param nRetries: Number of times to rety before giving up. + @param result: ICMPEchoReply that will hold the result. + */ + void operator()(const IPAddress& addr, int nRetries, EthernetICMPEchoReply& result); + + + + /* + Use setPayload to set custom data for all ICMP packets + by passing it an array of [REQ_DATASIZE]. E.g. + uint8_t myPayload[REQ_DATASIZE] = { ... whatever ...}; + ICMPPing ping(pingSocket, (uint16_t)random(0, 255)); + ping.setPayload(myPayload); + // ... as usual ... + + @param payload: pointer to start of REQ_DATASIZE array of bytes to use as payload + + */ + void setPayload(uint8_t * payload); + +#ifdef ICMPPING_ASYNCH_ENABLE + /* + Asynchronous ping methods -- only enabled if ICMPPING_ASYNCH_ENABLE is defined, above. + + These methods are used to start a ping request, go do something else, and + come back later to check if the results are in. A complete example is in the + examples directory but the gist of it is E.g. + + + // say we're in some function, to simplify things... + IPAddress pingAddr(74,125,26,147); // ip address to ping + + EthernetICMPPing ping(0, (uint16_t)random(0, 255)); + EthernetICMPEchoReply theResult; + + if (! asyncStart(pingAddr, 3, theResult)) + { + // well, this didn't start off on the right foot + Serial.print("Echo request send failed; "); + Serial.println((int)theResult.status); + + // + return; // forget about this + } + + // ok, ping has started... + while (! ping.asyncComplete(theResult)) { + + // whatever needs handling while we wait on results + doSomeStuff(); + doSomeOtherStuff(); + delay(30); + + } + + // we get here means we either got a response, or timed out... + if (theResult.status == SUCCESS) + { + // yay... do something. + } else { + // boooo... do something else. + } + + return; + + + */ + + + /* + asyncStart -- begins a new ping request, asynchronously. Parameters are the + same as for regular ping, but the method returns false on error. + + @param addr: IP address to ping, as an array of four octets. + @param nRetries: Number of times to rety before giving up. + @param result: ICMPEchoReply that will hold a status == ASYNC_SENT on success. + @return: true on async request sent, false otherwise. + @author: Pat Deegan, http://psychogenic.com + */ + bool asyncStart(const IPAddress& addr, int nRetries, EthernetICMPEchoReply& result); + + + /* + asyncComplete -- check if the asynchronous ping is done. + This can be either because of a successful outcome (reply received) + or because of an error/timeout. + + @param result: ICMPEchoReply that will hold the result. + @return: true if the result ICMPEchoReply contains the status/other data, + false if we're still waiting for it to complete. + @author: Pat Deegan, http://psychogenic.com + */ + bool asyncComplete(EthernetICMPEchoReply& result); +#endif + +private: + + // holds the timeout, in ms, for all objects of this class. + static uint16_t ping_timeout; + + void openSocket(); + + Status sendEchoRequest(const IPAddress& addr, const EthernetICMPEcho& echoReq); + void receiveEchoReply(const EthernetICMPEcho& echoReq, const IPAddress& addr, EthernetICMPEchoReply& echoReply); + + + +#ifdef ICMPPING_ASYNCH_ENABLE + // extra internal state/methods used when asynchronous pings + // are enabled. + bool asyncSend(EthernetICMPEchoReply& result); + uint8_t _curSeq; + uint8_t _numRetries; + icmp_time_t _asyncstart; + Status _asyncstatus; + IPAddress _addr; +#endif + uint8_t _id; + uint8_t _nextSeq; + SOCKET _socket; + uint8_t _attempt; + + uint8_t _payload[REQ_DATASIZE]; +}; + +#pragma pack(1) + +#endif \ No newline at end of file diff --git a/src/socket.cpp b/src/socket.cpp index f059dc92..46cdc067 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -21,6 +21,13 @@ #include #include "Ethernet.h" #include "utility/w5100.h" +#include "EthernetIcmp.h" + +#ifdef ICMPPING_INSERT_YIELDS +#define ICMPPING_DOYIELD() delay(2) +#else +#define ICMPPING_DOYIELD() +#endif #if ARDUINO >= 156 && !defined(ARDUINO_ARCH_PIC32) extern void yield(void); @@ -537,3 +544,110 @@ bool EthernetClass::socketSendUDP(uint8_t s) return true; } +void EthernetICMPPing::receiveEchoReply(const EthernetICMPEcho& echoReq, const IPAddress& addr, EthernetICMPEchoReply& echoReply) +{ + icmp_time_t start = millis(); + while (millis() - start < ping_timeout) + { + + if (getSnRX_RSR(_socket) < 1) + { + // take a break, maybe let platform do + // some background work (like on ESP8266) + ICMPPING_DOYIELD(); + continue; + } + + // ah! we did receive something... check it out. + + uint8_t ipHeader[6]; + uint8_t buffer = W5100.readSnRX_RD(_socket); + read_data(_socket, (uint16_t) buffer, ipHeader, sizeof(ipHeader)); + buffer += sizeof(ipHeader); + for (int i = 0; i < 4; ++i) + echoReply.addr[i] = ipHeader[i]; + uint8_t dataLen = ipHeader[4]; + dataLen = (dataLen << 8) + ipHeader[5]; + + uint8_t serialized[sizeof(EthernetICMPEcho)]; + if (dataLen > sizeof(EthernetICMPEcho)) + dataLen = sizeof(EthernetICMPEcho); + read_data(_socket, (uint16_t) buffer, serialized, dataLen); + echoReply.data.deserialize(serialized); + + buffer += dataLen; + W5100.writeSnRX_RD(_socket, buffer); + W5100.execCmdSn(_socket, Sock_RECV); + + echoReply.ttl = W5100.readSnTTL(_socket); + + // Since there aren't any ports in ICMP, we need to manually inspect the response + // to see if it originated from the request we sent out. + switch (echoReply.data.icmpHeader.type) { + case ICMP_ECHOREP: { + if (echoReply.data.id == echoReq.id + && echoReply.data.seq == echoReq.seq) { + echoReply.status = SUCCESS; + return; + } + break; + } + case TIME_EXCEEDED: { + uint8_t * sourceIpHeader = echoReply.data.payload; + unsigned int ipHeaderSize = (sourceIpHeader[0] & 0x0F) * 4u; + uint8_t * sourceIcmpHeader = echoReply.data.payload + ipHeaderSize; + + // The destination ip address in the originating packet's IP header. + IPAddress sourceDestAddress(sourceIpHeader + ipHeaderSize - 4); + + if (!(sourceDestAddress == addr)) + continue; + + uint16_t sourceId = ntohs(*(uint16_t * )(sourceIcmpHeader + 4)); + uint16_t sourceSeq = ntohs(*(uint16_t * )(sourceIcmpHeader + 6)); + + if (sourceId == echoReq.id && sourceSeq == echoReq.seq) { + echoReply.status = BAD_RESPONSE; + return; + } + break; + } + } + + + } + echoReply.status = NO_RESPONSE; +} + +Status EthernetICMPPing::sendEchoRequest(const IPAddress& addr, const EthernetICMPEcho& echoReq) +{ + // I wish there were a better way of doing this, but if we use the uint32_t + // cast operator, we're forced to (1) cast away the constness, and (2) deal + // with an endianness nightmare. + uint8_t addri [] = {addr[0], addr[1], addr[2], addr[3]}; + W5100.writeSnDIPR(_socket, addri); + W5100.writeSnTTL(_socket, 255); + // The port isn't used, becuause ICMP is a network-layer protocol. So we + // write zero. This probably isn't actually necessary. + W5100.writeSnDPORT(_socket, 0); + + uint8_t serialized [sizeof(EthernetICMPEcho)]; + echoReq.serialize(serialized); + + //W5100.send_data_processing(_socket, serialized, sizeof(EthernetICMPEcho)); + write_data(_socket, 0, serialized, sizeof(EthernetICMPEcho)); + W5100.execCmdSn(_socket, Sock_SEND); + + while ((W5100.readSnIR(_socket) & SnIR::SEND_OK) != SnIR::SEND_OK) + { + if (W5100.readSnIR(_socket) & SnIR::TIMEOUT) + { + W5100.writeSnIR(_socket, (SnIR::SEND_OK | SnIR::TIMEOUT)); + return SEND_TIMEOUT; + } + + ICMPPING_DOYIELD(); + } + W5100.writeSnIR(_socket, SnIR::SEND_OK); + return SUCCESS; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h new file mode 100644 index 00000000..0dfed7b5 --- /dev/null +++ b/src/util.h @@ -0,0 +1,14 @@ +#ifndef UTIL_H +#define UTIL_H + +//#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) +#define htons(x) ( (((x)&0xFF)<<8) | (((x)&0xFF00)>>8) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif \ No newline at end of file diff --git a/src/utility/w5100.cpp b/src/utility/w5100.cpp index 4ae4ee7a..4b0ca1ce 100644 --- a/src/utility/w5100.cpp +++ b/src/utility/w5100.cpp @@ -99,18 +99,20 @@ uint8_t W5100Class::init(void) // until the reset pulse is ended. If your hardware has a shorter // reset time, this can be edited or removed. delay(560); - //Serial.println("w5100 init"); + //SerialUSB.println(ss_pin); SPI.begin(); initSS(); resetSS(); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - + // SerialUSB.println("SPI inizializzato"); // Attempt W5200 detection first, because W5200 does not properly // reset its SPI state when CS goes high (inactive). Communication // from detecting the other chips can leave the W5200 in a state // where it won't recover, unless given a reset pulse. if (isW5200()) { + // SerialUSB.println("isW5200"); + CH_BASE_MSB = 0x40; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 @@ -136,6 +138,7 @@ uint8_t W5100Class::init(void) // SPI well with this chip. It appears to be very resilient, // so try it after the fragile W5200 } else if (isW5500()) { + // SerialUSB.println("isW5500"); CH_BASE_MSB = 0x10; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 @@ -163,6 +166,7 @@ uint8_t W5100Class::init(void) // communication. W5100 is also the only chip without a VERSIONR // register for identification, so we check this last. } else if (isW5100()) { + // SerialUSB.println("isW5100"); CH_BASE_MSB = 0x04; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 @@ -197,6 +201,7 @@ uint8_t W5100Class::init(void) return 1; // successful init } + // Soft reset the Wiznet chip, by writing to its MR register reset bit uint8_t W5100Class::softReset(void) { @@ -234,7 +239,7 @@ uint8_t W5100Class::isW5100(void) uint8_t W5100Class::isW5200(void) { chip = 52; - //Serial.println("w5100.cpp: detect W5200 chip"); + // SerialUSB.println("w5100.cpp: detect W5200 chip"); if (!softReset()) return 0; writeMR(0x08); if (readMR() != 0x08) return 0; @@ -243,17 +248,17 @@ uint8_t W5100Class::isW5200(void) writeMR(0x00); if (readMR() != 0x00) return 0; int ver = readVERSIONR_W5200(); - //Serial.print("version="); - //Serial.println(ver); + // SerialUSB.print("version="); + // SerialUSB.println(ver); if (ver != 3) return 0; - //Serial.println("chip is W5200"); + // SerialUSB.println("chip is W5200"); return 1; } uint8_t W5100Class::isW5500(void) { chip = 55; - //Serial.println("w5100.cpp: detect W5500 chip"); + // SerialUSB.println("w5100.cpp: detect W5500 chip"); if (!softReset()) return 0; writeMR(0x08); if (readMR() != 0x08) return 0; @@ -262,10 +267,10 @@ uint8_t W5100Class::isW5500(void) writeMR(0x00); if (readMR() != 0x00) return 0; int ver = readVERSIONR_W5500(); - //Serial.print("version="); - //Serial.println(ver); + // SerialUSB.print("version="); + // SerialUSB.println(ver); if (ver != 4) return 0; - //Serial.println("chip is W5500"); + // SerialUSB.println("chip is W5500"); return 1; } diff --git a/src/utility/w5100.h b/src/utility/w5100.h index a262d088..55d67ed3 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -16,6 +16,7 @@ #include #include +#include // Safe for all chips #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) @@ -33,7 +34,6 @@ #error "Ethernet.h must be included before w5100.h" #endif - // Arduino 101's SPI can not run faster than 8 MHz. #if defined(ARDUINO_ARCH_ARC32) #undef SPI_ETHERNET_SETTINGS @@ -49,8 +49,7 @@ #endif -// Industruino D21G can't use W5500 faster than 4 MHz -#if defined(INDIO_H_) +#if defined(INDUSTRUINO) #undef SPI_ETHERNET_SETTINGS #define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) #endif @@ -150,7 +149,6 @@ class W5100Class { inline void setRetransmissionTime(uint16_t timeout) { if (chip == 55) writeRTR_W5500(timeout); else writeRTR_W5100(timeout); } inline void setRetransmissionCount(uint8_t retry) { if (chip == 55) writeRCR_W5500(retry); else writeRCR_W5100(retry); } - static void execCmdSn(SOCKET s, SockCMD _cmd); @@ -232,6 +230,7 @@ class W5100Class { __GP_REGISTER16(PMRU, 0x0026); // PPP Maximum Segment Size + #undef __GP_REGISTER8 #undef __GP_REGISTER16 #undef __GP_REGISTER_N @@ -320,8 +319,8 @@ class W5100Class { private: static uint8_t chip; - static uint8_t ss_pin; static uint8_t softReset(void); + static uint8_t ss_pin; static uint8_t isW5100(void); static uint8_t isW5200(void); static uint8_t isW5500(void); @@ -472,22 +471,4 @@ extern W5100Class W5100; -#endif - -#ifndef UTIL_H -#define UTIL_H - -#ifndef htons - -#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) -#define ntohs(x) htons(x) - -#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ - ((x)<< 8 & 0x00FF0000UL) | \ - ((x)>> 8 & 0x0000FF00UL) | \ - ((x)>>24 & 0x000000FFUL) ) -#define ntohl(x) htonl(x) - -#endif // !defined(htons) - #endif From 48ea95602d023d7cf2db52443bdd126a88e9e820 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sun, 21 Feb 2021 13:46:46 +0100 Subject: [PATCH 04/16] Update w5100.h Addeed automatic spi setting for industruino --- src/utility/w5100.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utility/w5100.h b/src/utility/w5100.h index 55d67ed3..9c7dc9b7 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -49,12 +49,14 @@ #endif -#if defined(INDUSTRUINO) +// Industruino can't go faster than 4 MHz +#if defined(ARDUINO_SAMD_INDUSTRUINO_D21G) #undef SPI_ETHERNET_SETTINGS #define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) #endif + typedef uint8_t SOCKET; class SnMR { From b2db43a7ef12e10d42f4a83aaed7c40030e115f1 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sun, 21 Feb 2021 13:53:09 +0100 Subject: [PATCH 05/16] Update README.adoc --- README.adoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.adoc b/README.adoc index 4dfea8da..2aed73e9 100644 --- a/README.adoc +++ b/README.adoc @@ -1,3 +1,10 @@ +Customized library based on the original one. +- Added correct resistry definitions for W5500 +- Corrected minor problems +- added automatic spi settings for Industruino ethernet module +- Included ICMP ping functions from BlakeFoster ICMPPing library + + = Ethernet Library for Arduino = With the Arduino Ethernet Shield, this library allows an Arduino board to connect to the internet. From d916121d93b7caee6ffb9a03f012729f4365c389 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sun, 21 Feb 2021 13:53:34 +0100 Subject: [PATCH 06/16] Update README.adoc --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 2aed73e9..92e71427 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,5 @@ Customized library based on the original one. -- Added correct resistry definitions for W5500 +- Added correct registry definitions for W5500 - Corrected minor problems - added automatic spi settings for Industruino ethernet module - Included ICMP ping functions from BlakeFoster ICMPPing library From 3f5693ae3a9536df98b9dcf06a5423700c88f808 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sun, 21 Feb 2021 13:54:25 +0100 Subject: [PATCH 07/16] Update README.adoc --- README.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.adoc b/README.adoc index 92e71427..7af51481 100644 --- a/README.adoc +++ b/README.adoc @@ -1,10 +1,15 @@ Customized library based on the original one. + - Added correct registry definitions for W5500 + - Corrected minor problems + - added automatic spi settings for Industruino ethernet module + - Included ICMP ping functions from BlakeFoster ICMPPing library + = Ethernet Library for Arduino = With the Arduino Ethernet Shield, this library allows an Arduino board to connect to the internet. From dfba1570c77033e6d998b592f4c64c24e42b094c Mon Sep 17 00:00:00 2001 From: felmue Date: Fri, 4 Jun 2021 05:42:30 +0200 Subject: [PATCH 08/16] Add closeSocket function --- src/EthernetICMP.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EthernetICMP.h b/src/EthernetICMP.h index e1e69e72..fd2893f5 100644 --- a/src/EthernetICMP.h +++ b/src/EthernetICMP.h @@ -303,6 +303,7 @@ class EthernetICMPPing static uint16_t ping_timeout; void openSocket(); + void closeSocket(); Status sendEchoRequest(const IPAddress& addr, const EthernetICMPEcho& echoReq); void receiveEchoReply(const EthernetICMPEcho& echoReq, const IPAddress& addr, EthernetICMPEchoReply& echoReply); @@ -329,4 +330,4 @@ class EthernetICMPPing #pragma pack(1) -#endif \ No newline at end of file +#endif From 37ddf2c292e484d4a8babfd019f39ea653a4ca80 Mon Sep 17 00:00:00 2001 From: felmue Date: Fri, 4 Jun 2021 05:58:23 +0200 Subject: [PATCH 09/16] Fix async ping From the W5500 IPRAW documentation (http://www.wizwiki.net/wiki/lib/exe/fetch.php/products:w5500:w5500_ap_ipraw_v100e.pdf): 'After initialization of W5500, the Ping Reply is processed automatically. However, be aware that the Hardwired Ping Reply Logic is disabled if ICMP is opened as SOCKET n in IPRAW mode.' --- src/EthernetICMP.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/EthernetICMP.cpp b/src/EthernetICMP.cpp index d500e2d6..6e2d8fd2 100644 --- a/src/EthernetICMP.cpp +++ b/src/EthernetICMP.cpp @@ -159,6 +159,11 @@ void EthernetICMPPing::openSocket() W5100.execCmdSn(_socket, Sock_OPEN); } +void EthernetICMPPing::closeSocket() +{ + W5100.execCmdSn(_socket, Sock_CLOSE); + W5100.writeSnIR(_socket, 0xFF); +} void EthernetICMPPing::operator()(const IPAddress& addr, int nRetries, EthernetICMPEchoReply& result) @@ -256,16 +261,24 @@ bool EthernetICMPPing::asyncComplete(EthernetICMPEchoReply& result) // - failed to send; or // - are no longer waiting on this packet. // either way, we're done + + // Close RAW socket to allow device being pinged again + closeSocket(); + return true; } - if (W5100.getRXReceivedSize(_socket)) + if (W5100.readSnRX_SIZE(_socket)) { // ooooh, we've got a pending reply EthernetICMPEcho echoReq(ICMP_ECHOREQ, _id, _curSeq, _payload); receiveEchoReply(echoReq, _addr, result); _asyncstatus = result.status; // make note of this status, whatever it is. + + // Close RAW socket to allow device being pinged again + closeSocket(); + return true; // whatever the result of the receiveEchoReply(), the async op is done. } @@ -286,6 +299,10 @@ bool EthernetICMPPing::asyncComplete(EthernetICMPEchoReply& result) // this send has failed. too bad, // we are done. + + // Close RAW socket to allow device being pinged again + closeSocket(); + return true; } @@ -293,6 +310,10 @@ bool EthernetICMPPing::asyncComplete(EthernetICMPEchoReply& result) // hello? is anybody out there? // guess not: result.status = NO_RESPONSE; + + // Close RAW socket to allow device being pinged again + closeSocket(); + return true; } @@ -301,4 +322,4 @@ bool EthernetICMPPing::asyncComplete(EthernetICMPEchoReply& result) } -#endif /* ICMPPING_ASYNCH_ENABLE */ \ No newline at end of file +#endif /* ICMPPING_ASYNCH_ENABLE */ From 938108fa3280e5f95d68109b9a5cb625934b89e9 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Fri, 31 Dec 2021 15:45:10 +0100 Subject: [PATCH 10/16] Update Ethernet.cpp Merged some ESP8266 code from the main ERthernet lib --- src/Ethernet.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 0e30eaa6..462b6255 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -88,7 +88,11 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress g //SerialUSB.println("5"); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setMACAddress(mac); -#if ARDUINO > 106 || TEENSYDUINO > 121 +#ifdef ESP8266 + W5100.setIPAddress(&ip[0]); + W5100.setGatewayIp(&gateway[0]); + W5100.setSubnetMask(&subnet[0]); +#elif ARDUINO > 106 || TEENSYDUINO > 121 W5100.setIPAddress(ip._address.bytes); W5100.setGatewayIp(gateway._address.bytes); W5100.setSubnetMask(subnet._address.bytes); From 7468995a0674ce9dbacad3017eb06a3873f26a77 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Fri, 31 Dec 2021 16:11:01 +0100 Subject: [PATCH 11/16] Update w5100.h Merged the ifndef htons section from main branch --- src/utility/w5100.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/utility/w5100.h b/src/utility/w5100.h index 9c7dc9b7..7859481c 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -473,4 +473,32 @@ extern W5100Class W5100; +#endif + + +#ifndef UTIL_H +#define UTIL_H + +#ifndef htons +// The host order of the Arduino platform is little endian. +// Sometimes it is desired to convert to big endian (or +// network order) + +// Host to Network short +#define htons(x) ( (((x)&0xFF)<<8) | (((x)>>8)&0xFF) ) + +// Network to Host short +#define ntohs(x) htons(x) + +// Host to Network long +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) + +// Network to Host long +#define ntohl(x) htonl(x) + +#endif // !defined(htons) + #endif From 72535212a96f2a51b4d691a51710d19cc97f52b8 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 1 Jan 2022 16:55:27 +0100 Subject: [PATCH 12/16] Update Ethernet.cpp --- src/Ethernet.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 462b6255..2e126da7 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -28,7 +28,6 @@ DhcpClass* EthernetClass::_dhcp = NULL; int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { - //SerialUSB.println("0"); static DhcpClass s_dhcp; _dhcp = &s_dhcp; // Initialise the basic info @@ -56,7 +55,6 @@ int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long resp void EthernetClass::begin(uint8_t *mac, IPAddress ip) { - //SerialUSB.println("1"); // Assume the DNS server will be the machine on the same network as the local IP // but with last octet being '1' IPAddress dns = ip; @@ -66,7 +64,6 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip) void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) { - //SerialUSB.println("2"); // Assume the gateway will be the machine on the same network as the local IP // but with last octet being '1' IPAddress gateway = ip; @@ -76,16 +73,13 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { - //SerialUSB.println("3"); IPAddress subnet(255, 255, 255, 0); begin(mac, ip, dns, gateway, subnet); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - //SerialUSB.println("4"); if (W5100.init() == 0) return; - //SerialUSB.println("5"); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setMACAddress(mac); #ifdef ESP8266 From adb09bd8130f50821ef42e5e522fb5e6d668aa7d Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 1 Jan 2022 16:58:35 +0100 Subject: [PATCH 13/16] Update Ethernet.cpp --- src/Ethernet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 2e126da7..9257090c 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -30,6 +30,7 @@ int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long resp { static DhcpClass s_dhcp; _dhcp = &s_dhcp; + // Initialise the basic info if (W5100.init() == 0) return 0; SPI.beginTransaction(SPI_ETHERNET_SETTINGS); From 2f527db2d24ffb7c370ceb7e7d0dec91f94f8afa Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 1 Jan 2022 17:12:06 +0100 Subject: [PATCH 14/16] Update w5100.cpp --- src/utility/w5100.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/utility/w5100.cpp b/src/utility/w5100.cpp index 4b0ca1ce..446462af 100644 --- a/src/utility/w5100.cpp +++ b/src/utility/w5100.cpp @@ -99,20 +99,18 @@ uint8_t W5100Class::init(void) // until the reset pulse is ended. If your hardware has a shorter // reset time, this can be edited or removed. delay(560); - //SerialUSB.println(ss_pin); + //Serial.println("w5100 init"); SPI.begin(); initSS(); resetSS(); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - // SerialUSB.println("SPI inizializzato"); + // Attempt W5200 detection first, because W5200 does not properly // reset its SPI state when CS goes high (inactive). Communication // from detecting the other chips can leave the W5200 in a state // where it won't recover, unless given a reset pulse. if (isW5200()) { - // SerialUSB.println("isW5200"); - CH_BASE_MSB = 0x40; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 @@ -138,7 +136,6 @@ uint8_t W5100Class::init(void) // SPI well with this chip. It appears to be very resilient, // so try it after the fragile W5200 } else if (isW5500()) { - // SerialUSB.println("isW5500"); CH_BASE_MSB = 0x10; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 @@ -166,7 +163,6 @@ uint8_t W5100Class::init(void) // communication. W5100 is also the only chip without a VERSIONR // register for identification, so we check this last. } else if (isW5100()) { - // SerialUSB.println("isW5100"); CH_BASE_MSB = 0x04; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 @@ -239,7 +235,7 @@ uint8_t W5100Class::isW5100(void) uint8_t W5100Class::isW5200(void) { chip = 52; - // SerialUSB.println("w5100.cpp: detect W5200 chip"); + // Serial.println("w5100.cpp: detect W5200 chip"); if (!softReset()) return 0; writeMR(0x08); if (readMR() != 0x08) return 0; @@ -248,17 +244,17 @@ uint8_t W5100Class::isW5200(void) writeMR(0x00); if (readMR() != 0x00) return 0; int ver = readVERSIONR_W5200(); - // SerialUSB.print("version="); - // SerialUSB.println(ver); + // Serial.print("version="); + // Serial.println(ver); if (ver != 3) return 0; - // SerialUSB.println("chip is W5200"); + // Serial.println("chip is W5200"); return 1; } uint8_t W5100Class::isW5500(void) { chip = 55; - // SerialUSB.println("w5100.cpp: detect W5500 chip"); + // Serial.println("w5100.cpp: detect W5500 chip"); if (!softReset()) return 0; writeMR(0x08); if (readMR() != 0x08) return 0; @@ -267,10 +263,10 @@ uint8_t W5100Class::isW5500(void) writeMR(0x00); if (readMR() != 0x00) return 0; int ver = readVERSIONR_W5500(); - // SerialUSB.print("version="); - // SerialUSB.println(ver); + // Serial.print("version="); + // Serial.println(ver); if (ver != 4) return 0; - // SerialUSB.println("chip is W5500"); + // Serial.println("chip is W5500"); return 1; } From 25238788c5c22f2f0c0e8ad11c4c4d4e7bc6c454 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 1 Jan 2022 17:12:09 +0100 Subject: [PATCH 15/16] Update w5100.h --- src/utility/w5100.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utility/w5100.h b/src/utility/w5100.h index 7859481c..f5aa26d5 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -34,6 +34,7 @@ #error "Ethernet.h must be included before w5100.h" #endif + // Arduino 101's SPI can not run faster than 8 MHz. #if defined(ARDUINO_ARCH_ARC32) #undef SPI_ETHERNET_SETTINGS @@ -321,8 +322,8 @@ class W5100Class { private: static uint8_t chip; - static uint8_t softReset(void); static uint8_t ss_pin; + static uint8_t softReset(void); static uint8_t isW5100(void); static uint8_t isW5200(void); static uint8_t isW5500(void); From 1a18bb67c303828b206426828c22d22ee4cdeb63 Mon Sep 17 00:00:00 2001 From: masterx1981 <76602320+masterx1981@users.noreply.github.com> Date: Sat, 1 Jan 2022 17:16:57 +0100 Subject: [PATCH 16/16] Update w5100.cpp --- src/utility/w5100.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/utility/w5100.cpp b/src/utility/w5100.cpp index 446462af..4ae4ee7a 100644 --- a/src/utility/w5100.cpp +++ b/src/utility/w5100.cpp @@ -197,7 +197,6 @@ uint8_t W5100Class::init(void) return 1; // successful init } - // Soft reset the Wiznet chip, by writing to its MR register reset bit uint8_t W5100Class::softReset(void) { @@ -235,7 +234,7 @@ uint8_t W5100Class::isW5100(void) uint8_t W5100Class::isW5200(void) { chip = 52; - // Serial.println("w5100.cpp: detect W5200 chip"); + //Serial.println("w5100.cpp: detect W5200 chip"); if (!softReset()) return 0; writeMR(0x08); if (readMR() != 0x08) return 0; @@ -244,17 +243,17 @@ uint8_t W5100Class::isW5200(void) writeMR(0x00); if (readMR() != 0x00) return 0; int ver = readVERSIONR_W5200(); - // Serial.print("version="); - // Serial.println(ver); + //Serial.print("version="); + //Serial.println(ver); if (ver != 3) return 0; - // Serial.println("chip is W5200"); + //Serial.println("chip is W5200"); return 1; } uint8_t W5100Class::isW5500(void) { chip = 55; - // Serial.println("w5100.cpp: detect W5500 chip"); + //Serial.println("w5100.cpp: detect W5500 chip"); if (!softReset()) return 0; writeMR(0x08); if (readMR() != 0x08) return 0; @@ -263,10 +262,10 @@ uint8_t W5100Class::isW5500(void) writeMR(0x00); if (readMR() != 0x00) return 0; int ver = readVERSIONR_W5500(); - // Serial.print("version="); - // Serial.println(ver); + //Serial.print("version="); + //Serial.println(ver); if (ver != 4) return 0; - // Serial.println("chip is W5500"); + //Serial.println("chip is W5500"); return 1; }