diff options
author | David Crocker <dcrocker@eschertech.com> | 2016-12-29 17:10:53 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2016-12-29 17:11:08 +0300 |
commit | c5e6d7179c5894cb0fcb56a018033080776cab5e (patch) | |
tree | a4e84e86c17f97e689ba025ca98b159d154a8f2a /src | |
parent | 13f914ad7dd10e9c1fc9a0899e79ff609098a550 (diff) |
DuetEthernet support + minor changes
Diffstat (limited to 'src')
58 files changed, 839 insertions, 4812 deletions
diff --git a/src/Configuration.h b/src/Configuration.h index a2475a36..06186fdb 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -165,7 +165,10 @@ const size_t RESERVED_OUTPUT_BUFFERS = 2; // Number of reserved output buffers // Move system -const float DEFAULT_FEEDRATE = 3000.0; // The initial requested feed rate after resetting the printer +const float DefaultFeedrate = 3000.0; // The initial requested feed rate after resetting the printer, in mm/min +const float DefaultRetractSpeed = 1000.0; // The default firmware retraction and un-retraction speed, in mm +const float DefaultRetractLength = 1.0; + const float DEFAULT_IDLE_TIMEOUT = 30.0; // Seconds const float DEFAULT_IDLE_CURRENT_FACTOR = 0.3; // Proportion of normal motor current that we use for idle hold diff --git a/src/Duet/Network.cpp b/src/Duet/Network.cpp index 90cbeb35..bba5ffa4 100644 --- a/src/Duet/Network.cpp +++ b/src/Duet/Network.cpp @@ -109,7 +109,7 @@ uint16_t sendingWindowSize, sentDataOutstanding; uint8_t sendingRetries; err_t writeResult, outputResult; -static uint16_t httpPort = DefaultHttpPort; +static Port httpPort = DefaultHttpPort; /*-----------------------------------------------------------------------------------*/ @@ -296,6 +296,10 @@ Network::Network(Platform* p) : state(NetworkInactive), isEnabled(true), resetCallback(false), dataCs(nullptr), ftpCs(nullptr), telnetCs(nullptr), freeConnections(nullptr) { +} + +void Network::Init() +{ for (size_t i = 0; i < NETWORK_TRANSACTION_COUNT; i++) { freeTransactions = new NetworkTransaction(freeTransactions); @@ -309,10 +313,6 @@ Network::Network(Platform* p) : } strcpy(hostname, HOSTNAME); -} - -void Network::Init() -{ init_ethernet(); httpd_init(); @@ -323,98 +323,96 @@ void Network::Init() longWait = platform->Time(); } -void Network::Spin() +void Network::Spin(bool full) { - // Basically we can't do anything if we can't interact with LWIP - - if (!LockLWIP()) - { - platform->ClassReport(longWait); - return; - } - - if (state == NetworkObtainingIP || state == NetworkActive) + if (LockLWIP()) // basically we can't do anything if we can't interact with LWIP { - // Is the link still up? - if (!ethernet_link_established()) - { - state = NetworkEstablishingLink; - UnlockLWIP(); - - platform->ClassReport(longWait); - return; - } - - // See if we can read any packets. They may include DHCP responses too - ethernet_task(); - if (resetCallback) - { - resetCallback = false; - ethernet_set_rx_callback(ðernet_rx_callback); - } - - // Have we obtained a valid IP address yet? - if (state == NetworkObtainingIP) + if (state == NetworkObtainingIP || state == NetworkActive) { - const uint8_t *ip = ethernet_get_ipaddress(); - if (ip[0] != 0 && ip[1] != 0 && ip[2] != 0 && ip[3] != 0) + // Is the link still up? + if (!ethernet_link_established()) { - // Yes - we're good to go now - state = NetworkActive; + state = NetworkEstablishingLink; + UnlockLWIP(); - // Send mDNS announcement so that some routers can perform hostname mapping - // if ths board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N) - mdns_announce(); + platform->ClassReport(longWait); + return; } - } - // See if we can send anything - NetworkTransaction *transaction = writingTransactions; - if (transaction != nullptr && sendingConnection == nullptr) - { - if (transaction->next != nullptr) + // See if we can read any packets. They may include DHCP responses too + ethernet_task(); + if (resetCallback) { - // Data is supposed to be sent and the last packet has been acknowledged. - // Rotate the transactions so every client is served even while multiple files are sent - NetworkTransaction *next = transaction->next; - writingTransactions = next; - AppendTransaction(&writingTransactions, transaction); - transaction = next; + resetCallback = false; + ethernet_set_rx_callback(ðernet_rx_callback); } - if (transaction->Send()) + // Have we obtained a valid IP address yet? + if (state == NetworkObtainingIP) { - // This transaction can be released, do this here - writingTransactions = transaction->next; - PrependTransaction(&freeTransactions, transaction); + const uint8_t *ip = ethernet_get_ipaddress(); + if (ip[0] != 0 && ip[1] != 0 && ip[2] != 0 && ip[3] != 0) + { + // Yes - we're good to go now + state = NetworkActive; - // If there is more data to write on this connection, do it sometime soon - NetworkTransaction *nextWrite = transaction->nextWrite; - if (nextWrite != nullptr) + // Send mDNS announcement so that some routers can perform hostname mapping + // if ths board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N) + mdns_announce(); + } + } + + // See if we can send anything - only if full spin i.e. not in the middle of file i/o + if (full) + { + NetworkTransaction *transaction = writingTransactions; + if (transaction != nullptr && sendingConnection == nullptr) { - PrependTransaction(&writingTransactions, nextWrite); + if (transaction->next != nullptr) + { + // Data is supposed to be sent and the last packet has been acknowledged. + // Rotate the transactions so every client is served even while multiple files are sent + NetworkTransaction *next = transaction->next; + writingTransactions = next; + AppendTransaction(&writingTransactions, transaction); + transaction = next; + } + + if (transaction->Send()) + { + // This transaction can be released, do this here + writingTransactions = transaction->next; + PrependTransaction(&freeTransactions, transaction); + + // If there is more data to write on this connection, do it sometime soon + NetworkTransaction *nextWrite = transaction->nextWrite; + if (nextWrite != nullptr) + { + PrependTransaction(&writingTransactions, nextWrite); + } + } } } } - } - else if (state == NetworkEstablishingLink && ethernet_establish_link()) - { - if (!ethernetStarted) + else if (state == NetworkEstablishingLink && ethernet_establish_link()) { - start_ethernet(platform->GetIPAddress(), platform->NetMask(), platform->GateWay(), ðernet_status_callback); - ethernetStarted = true; + if (!ethernetStarted) + { + start_ethernet(platform->GetIPAddress(), platform->NetMask(), platform->GateWay(), ðernet_status_callback); + ethernetStarted = true; - // Initialise this one here, because it requires a configured IGMP network interface - mdns_responder_init(mdns_services, ARRAY_SIZE(mdns_services), mdns_txt_records); - } - else - { - ethernet_set_configuration(platform->GetIPAddress(), platform->NetMask(), platform->GateWay()); + // Initialise this one here, because it requires a configured IGMP network interface + mdns_responder_init(mdns_services, ARRAY_SIZE(mdns_services), mdns_txt_records); + } + else + { + ethernet_set_configuration(platform->GetIPAddress(), platform->NetMask(), platform->GateWay()); + } + state = NetworkObtainingIP; } - state = NetworkObtainingIP; - } - UnlockLWIP(); + UnlockLWIP(); + } platform->ClassReport(longWait); } @@ -800,7 +798,7 @@ void Network::PrependTransaction(NetworkTransaction* volatile* list, NetworkTran *list = r; } -void Network::OpenDataPort(uint16_t port) +void Network::OpenDataPort(Port port) { closingDataPort = false; tcp_pcb* pcb = tcp_new(); @@ -809,17 +807,17 @@ void Network::OpenDataPort(uint16_t port) tcp_accept(ftp_pasv_pcb, conn_accept); } -uint16_t Network::GetDataPort() const +Port Network::GetDataPort() const { return (closingDataPort || (ftp_pasv_pcb == nullptr) ? 0 : ftp_pasv_pcb->local_port); } -uint16_t Network::GetHttpPort() const +Port Network::GetHttpPort() const { return httpPort; } -void Network::SetHttpPort(uint16_t port) +void Network::SetHttpPort(Port port) { if (port != httpPort) { @@ -932,8 +930,8 @@ bool Network::AcquireTransaction(ConnectionState *cs) return true; } -/*static*/ uint16_t Network::GetLocalPort(Connection conn) { return conn->GetLocalPort(); } -/*static*/ uint16_t Network::GetRemotePort(Connection conn) { return conn->GetRemotePort(); } +/*static*/ Port Network::GetLocalPort(Connection conn) { return conn->GetLocalPort(); } +/*static*/ Port Network::GetRemotePort(Connection conn) { return conn->GetRemotePort(); } /*static*/ uint32_t Network::GetRemoteIP(Connection conn) { return conn->GetRemoteIP(); } /*static*/ bool Network::IsConnected(Connection conn) { return conn->IsConnected(); } /*static*/ bool Network::IsTerminated(Connection conn) { return conn->IsTerminated(); } diff --git a/src/Duet/Network.h b/src/Duet/Network.h index f31ccdd2..1c10844b 100644 --- a/src/Duet/Network.h +++ b/src/Duet/Network.h @@ -50,7 +50,7 @@ public: Network(Platform* p); void Init(); void Exit() {} - void Spin(); + void Spin(bool full); void Interrupt(); void Diagnostics(MessageType mtype); @@ -80,12 +80,12 @@ public: NetworkTransaction *GetTransaction(const ConnectionState *cs = nullptr); - void OpenDataPort(uint16_t port); - uint16_t GetDataPort() const; + void OpenDataPort(Port port); + Port GetDataPort() const; void CloseDataPort(); - void SetHttpPort(uint16_t port); - uint16_t GetHttpPort() const; + void SetHttpPort(Port port); + Port GetHttpPort() const; void SaveDataConnection(); void SaveFTPConnection(); @@ -95,8 +95,8 @@ public: bool AcquireDataTransaction(); bool AcquireTelnetTransaction(); - static uint16_t GetLocalPort(Connection conn); - static uint16_t GetRemotePort(Connection conn); + static Port GetLocalPort(Connection conn); + static Port GetRemotePort(Connection conn); static uint32_t GetRemoteIP(Connection conn); static bool IsConnected(Connection conn); static bool IsTerminated(Connection conn); diff --git a/src/Duet/NetworkDefs.h b/src/Duet/NetworkDefs.h index 81f2d593..ff0c95a3 100644 --- a/src/Duet/NetworkDefs.h +++ b/src/Duet/NetworkDefs.h @@ -1,12 +1,12 @@ /* - * NetworkCommon.h + * NetworkDefs.h * * Created on: 25 Dec 2016 * Author: David */ -#ifndef SRC_DUETNG_DUETETHERNET_NETWORKCOMMON_H_ -#define SRC_DUETNG_DUETETHERNET_NETWORKCOMMON_H_ +#ifndef SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ +#define SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ #include <cstdint> @@ -35,4 +35,4 @@ const Port TELNET_PORT = 23; // MSS is defined in lwip #include "Lwip/lwipopts.h" -#endif /* SRC_DUETNG_DUETETHERNET_NETWORKCOMMON_H_ */ +#endif /* SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ */ diff --git a/src/Duet/NetworkTransaction.cpp b/src/Duet/NetworkTransaction.cpp index 5c870f8a..fddcff09 100644 --- a/src/Duet/NetworkTransaction.cpp +++ b/src/Duet/NetworkTransaction.cpp @@ -603,12 +603,12 @@ uint32_t NetworkTransaction::GetRemoteIP() const return (cs != nullptr) ? cs->GetRemoteIP() : 0; } -uint16_t NetworkTransaction::GetRemotePort() const +Port NetworkTransaction::GetRemotePort() const { return (cs != nullptr) ? cs->GetRemotePort() : 0; } -uint16_t NetworkTransaction::GetLocalPort() const +Port NetworkTransaction::GetLocalPort() const { return (cs != nullptr) ? cs->GetLocalPort() : 0; } diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Client.h b/src/DuetNG/DuetEthernet/Ethernet3/Client.h deleted file mode 100644 index b8e5d935..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Client.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Client.h - Base class that provides Client - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef client_h -#define client_h -#include "Print.h" -#include "Stream.h" -#include "IPAddress.h" - -class Client : public Stream { - -public: - virtual int connect(IPAddress ip, uint16_t port) =0; - virtual int connect(const char *host, uint16_t port) =0; - virtual size_t write(uint8_t) =0; - virtual size_t write(const uint8_t *buf, size_t size) =0; - virtual int available() = 0; - virtual int read() = 0; - virtual int read(uint8_t *buf, size_t size) = 0; - virtual int peek() = 0; - virtual void flush() = 0; - virtual void stop() = 0; - virtual uint8_t connected() = 0; - virtual operator bool() = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Dhcp.cpp b/src/DuetNG/DuetEthernet/Ethernet3/Dhcp.cpp deleted file mode 100644 index 8b4cc219..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Dhcp.cpp +++ /dev/null @@ -1,520 +0,0 @@ -// DHCP Library v0.3 - April 25, 2009 -// Author: Jordan Terrell - blog.jordanterrell.com - -#include "utility/w5500.h" - -#include <cstring> -#include <cstdlib> -#include "Dhcp.h" -#include "Core.h" -#include "utility/util.h" - -extern "C" void debugPrintf(const char *fmt, ...); - -int DhcpClass::beginWithDHCP(const uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) -{ - _dhcpLeaseTime=0; - _dhcpT1=0; - _dhcpT2=0; - _lastCheck=0; - _timeout = timeout; - _responseTimeout = responseTimeout; - - reset_DHCP_lease(); - memcpy(_dhcpMacAddr, mac, sizeof(_dhcpMacAddr)); - _dhcp_state = STATE_DHCP_START; - return request_DHCP_lease(); -} - -void DhcpClass::reset_DHCP_lease(){ - // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp - memset(_dhcpLocalIp, 0, sizeof(_dhcpLocalIp)); - memset(_dhcpSubnetMask, 0, sizeof(_dhcpSubnetMask)); - memset(_dhcpGatewayIp, 0, sizeof(_dhcpGatewayIp)); - memset(_dhcpDhcpServerIp, 0, sizeof(_dhcpDhcpServerIp)); - memset(_dhcpDnsServerIp, 0, sizeof(_dhcpDnsServerIp)); -} - -//return:0 on error, 1 if request is sent and response is received -int DhcpClass::request_DHCP_lease() -{ - // Pick an initial transaction ID - _dhcpTransactionId = random(1UL, 2000UL); - _dhcpInitialTransactionId = _dhcpTransactionId; - - _dhcpUdpSocket.stop(); - if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) - { - return 0; // Couldn't get a socket - } - - presend_DHCP(); - - const unsigned long startTime = millis(); - bool hadError = false; - while(_dhcp_state != STATE_DHCP_LEASED && !hadError && (millis() - startTime) < _timeout) - { -#if 1 - { - uint8_t tmp = w5500.readPHYCFGR(); - uint8_t version = w5500.readVERSIONR(); - uint8_t macBuf[6]; - w5500.readSHAR(macBuf); - debugPrintf("Phy %02x ver %02x Mac %02x:%02x:%02x:%02x:%02x:%02x\n", - tmp, version, macBuf[0], macBuf[1], macBuf[2], macBuf[3], macBuf[4], macBuf[5]); - } -#endif - switch (_dhcp_state) - { - case STATE_DHCP_START: - debugPrintf("DHCP_START\n"); - _dhcpTransactionId++; - send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); - _dhcp_state = STATE_DHCP_DISCOVER; - break; - - case STATE_DHCP_DISCOVER: - { - debugPrintf("DHCP_DISCOVER\n"); - uint32_t respId; - const uint8_t messageType = parseDHCPResponse(_responseTimeout, respId); - if (messageType == DHCP_OFFER) - { - // We'll use the transaction ID that the offer came with, rather than the one we were up to - _dhcpTransactionId = respId; - send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); - _dhcp_state = STATE_DHCP_REQUEST; - } - else if (messageType == 255) - { - _dhcp_state = STATE_DHCP_START; -// hadError = true; - } - } - break; - - case STATE_DHCP_REQUEST: - { - debugPrintf("DHCP_REQUEST\n"); - uint32_t respId; - const uint8_t messageType = parseDHCPResponse(_responseTimeout, respId); - if (messageType == DHCP_ACK) - { - _dhcp_state = STATE_DHCP_LEASED; - debugPrintf("DHCP_LEASED\n"); - //use default lease time if we didn't get it - if (_dhcpLeaseTime == 0) - { - _dhcpLeaseTime = DEFAULT_LEASE; - } - //calculate T1 & T2 if we didn't get it - if (_dhcpT1 == 0) - { - //T1 should be 50% of _dhcpLeaseTime - _dhcpT1 = _dhcpLeaseTime >> 1; - } - if (_dhcpT2 == 0) - { - //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime - _dhcpT2 = _dhcpT1 << 1; - } - _renewInSec = _dhcpT1; - _rebindInSec = _dhcpT2; - } - else if (messageType == DHCP_NAK) - { - _dhcp_state = STATE_DHCP_START; - } - else if (messageType == 255) - { - _dhcp_state = STATE_DHCP_START; -// hadError = true; - } - } - break; - - case STATE_DHCP_REREQUEST: - debugPrintf("DHCP_REREQUEST\n"); - _dhcpTransactionId++; - send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); - _dhcp_state = STATE_DHCP_REQUEST; - break; - - default: - debugPrintf("Bad DHCP state\n"); - _dhcp_state = STATE_DHCP_START; - hadError = true; - } - } - - // We're done with the socket now - _dhcpUdpSocket.stop(); - _dhcpTransactionId++; - - return (_dhcp_state == STATE_DHCP_LEASED) ? 1 : 0; -} - -void DhcpClass::presend_DHCP() -{ -} - -void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) -{ - uint8_t buffer[32]; - memset(buffer, 0, 32); - IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address - - if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) - { - // FIXME Need to return errors - debugPrintf("Begin packet failed\n"); - return; - } - - buffer[0] = DHCP_BOOTREQUEST; // op - buffer[1] = DHCP_HTYPE10MB; // htype - buffer[2] = DHCP_HLENETHERNET; // hlen - buffer[3] = DHCP_HOPS; // hops - - // xid - unsigned long xid = htonl(_dhcpTransactionId); - memcpy(buffer + 4, &(xid), 4); - - // 8, 9 - seconds elapsed - buffer[8] = ((secondsElapsed & 0xff00) >> 8); - buffer[9] = (secondsElapsed & 0x00ff); - - // flags - unsigned short flags = htons(DHCP_FLAGSBROADCAST); - memcpy(buffer + 10, &(flags), 2); - - // ciaddr: already zeroed - // yiaddr: already zeroed - // siaddr: already zeroed - // giaddr: already zeroed - - //put data in w5500 transmit buffer - _dhcpUdpSocket.write(buffer, 28); - - memset(buffer, 0, 32); // clear local buffer - - memcpy(buffer, _dhcpMacAddr, 6); // chaddr - - //put data in w5500 transmit buffer - _dhcpUdpSocket.write(buffer, 16); - - memset(buffer, 0, 32); // clear local buffer - - // leave zeroed out for sname && file - // put in w5500 transmit buffer x 6 (192 bytes) - - for (int i = 0; i < 6; i++) - { - _dhcpUdpSocket.write(buffer, 32); - } - - // OPT - Magic Cookie - buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); - buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); - buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); - buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); - - // OPT - message type - buffer[4] = dhcpMessageType; - buffer[5] = 0x01; - buffer[6] = messageType; //DHCP_REQUEST; - - // OPT - client identifier - buffer[7] = dhcpClientIdentifier; - buffer[8] = 0x07; - buffer[9] = 0x01; - memcpy(buffer + 10, _dhcpMacAddr, 6); - - // OPT - host name - buffer[16] = hostName; - buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address - strcpy((char*)&(buffer[18]), HOST_NAME); - - printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); - printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); - printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); - - //put data in w5500 transmit buffer - _dhcpUdpSocket.write(buffer, 30); - - if(messageType == DHCP_REQUEST) - { - buffer[0] = dhcpRequestedIPaddr; - buffer[1] = 0x04; - buffer[2] = _dhcpLocalIp[0]; - buffer[3] = _dhcpLocalIp[1]; - buffer[4] = _dhcpLocalIp[2]; - buffer[5] = _dhcpLocalIp[3]; - - buffer[6] = dhcpServerIdentifier; - buffer[7] = 0x04; - buffer[8] = _dhcpDhcpServerIp[0]; - buffer[9] = _dhcpDhcpServerIp[1]; - buffer[10] = _dhcpDhcpServerIp[2]; - buffer[11] = _dhcpDhcpServerIp[3]; - - //put data in w5500 transmit buffer - _dhcpUdpSocket.write(buffer, 12); - } - - buffer[0] = dhcpParamRequest; - buffer[1] = 0x06; - buffer[2] = subnetMask; - buffer[3] = routersOnSubnet; - buffer[4] = dns; - buffer[5] = domainName; - buffer[6] = dhcpT1value; - buffer[7] = dhcpT2value; - buffer[8] = endOption; - - //put data in w5500 transmit buffer - _dhcpUdpSocket.write(buffer, 9); - - _dhcpUdpSocket.endPacket(); -} - -uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) -{ - uint8_t type = 0; - uint8_t opt_len = 0; - - const unsigned long startTime = millis(); - - while(_dhcpUdpSocket.parsePacket() <= 0) - { - if ((millis() - startTime) > responseTimeout) - { - debugPrintf("Response timed out\n"); - return 255; - } - delay(50); - } - - // start reading in the packet - RIP_MSG_FIXED fixedMsg; - _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); - - if (fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) - { - transactionId = ntohl(fixedMsg.xid); - if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) - { - // Need to read the rest of the packet here regardless - _dhcpUdpSocket.flush(); - return 0; - } - - memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); - - // Skip to the option part - // Doing this a byte at a time so we don't have to put a big buffer - // on the stack (as we don't have lots of memory lying around) - for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) - { - _dhcpUdpSocket.read(); // we don't care about the returned byte - } - - while (_dhcpUdpSocket.available() > 0) - { - switch (_dhcpUdpSocket.read()) - { - case endOption : - - break; - - case padOption : - - break; - - case dhcpMessageType : - - opt_len = _dhcpUdpSocket.read(); - type = _dhcpUdpSocket.read(); - break; - - case subnetMask : - - opt_len = _dhcpUdpSocket.read(); - _dhcpUdpSocket.read(_dhcpSubnetMask, 4); - break; - - case routersOnSubnet : - - opt_len = _dhcpUdpSocket.read(); - _dhcpUdpSocket.read(_dhcpGatewayIp, 4); - for (int i = 0; i < opt_len-4; i++) - { - _dhcpUdpSocket.read(); - } - break; - - case dns : - - opt_len = _dhcpUdpSocket.read(); - _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); - for (int i = 0; i < opt_len-4; i++) - { - _dhcpUdpSocket.read(); - } - break; - - case dhcpServerIdentifier : - - opt_len = _dhcpUdpSocket.read(); - if(((_dhcpDhcpServerIp[0] == 0) && (_dhcpDhcpServerIp[1] == 0) && (_dhcpDhcpServerIp[2] == 0) && (_dhcpDhcpServerIp[3] == 0)) || (IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP())) - { - _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); - } - else - { - // Skip over the rest of this option - while (opt_len--) - { - _dhcpUdpSocket.read(); - } - } - break; - - case dhcpT1value : - - opt_len = _dhcpUdpSocket.read(); - _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); - _dhcpT1 = ntohl(_dhcpT1); - break; - - case dhcpT2value : - - opt_len = _dhcpUdpSocket.read(); - _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); - _dhcpT2 = ntohl(_dhcpT2); - break; - - case dhcpIPaddrLeaseTime : - - opt_len = _dhcpUdpSocket.read(); - _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); - _dhcpLeaseTime = ntohl(_dhcpLeaseTime); - _renewInSec = _dhcpLeaseTime; - break; - - default : - - opt_len = _dhcpUdpSocket.read(); - // Skip over the rest of this option - while (opt_len--) - { - _dhcpUdpSocket.read(); - } - break; - } - } - } - - // Need to skip to end of the packet regardless here - _dhcpUdpSocket.flush(); - - return type; -} - - -/* - returns: - 0/DHCP_CHECK_NONE: nothing happened - 1/DHCP_CHECK_RENEW_FAIL: renew failed - 2/DHCP_CHECK_RENEW_OK: renew success - 3/DHCP_CHECK_REBIND_FAIL: rebind fail - 4/DHCP_CHECK_REBIND_OK: rebind success -*/ -int DhcpClass::checkLease(){ - //this uses a signed / unsigned trick to deal with millis overflow - unsigned long now = millis(); - signed long snow = (long)now; - int rc=DHCP_CHECK_NONE; - if (_lastCheck != 0){ - signed long factor; - //calc how many ms past the timeout we are - factor = snow - (long)_secTimeout; - //if on or passed the timeout, reduce the counters - if ( factor >= 0 ){ - //next timeout should be now plus 1000 ms minus parts of second in factor - _secTimeout = snow + 1000 - factor % 1000; - //how many seconds late are we, minimum 1 - factor = factor / 1000 +1; - - //reduce the counters by that mouch - //if we can assume that the cycle time (factor) is fairly constant - //and if the remainder is less than cycle time * 2 - //do it early instead of late - if(_renewInSec < factor*2 ) - _renewInSec = 0; - else - _renewInSec -= factor; - - if(_rebindInSec < factor*2 ) - _rebindInSec = 0; - else - _rebindInSec -= factor; - } - - //if we have a lease but should renew, do it - if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ - _dhcp_state = STATE_DHCP_REREQUEST; - rc = 1 + request_DHCP_lease(); - } - - //if we have a lease or is renewing but should bind, do it - if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ - //this should basically restart completely - _dhcp_state = STATE_DHCP_START; - reset_DHCP_lease(); - rc = 3 + request_DHCP_lease(); - } - } - else{ - _secTimeout = snow + 1000; - } - - _lastCheck = now; - return rc; -} - -IPAddress DhcpClass::getLocalIp() -{ - return IPAddress(_dhcpLocalIp); -} - -IPAddress DhcpClass::getSubnetMask() -{ - return IPAddress(_dhcpSubnetMask); -} - -IPAddress DhcpClass::getGatewayIp() -{ - return IPAddress(_dhcpGatewayIp); -} - -IPAddress DhcpClass::getDhcpServerIp() -{ - return IPAddress(_dhcpDhcpServerIp); -} - -IPAddress DhcpClass::getDnsServerIp() -{ - return IPAddress(_dhcpDnsServerIp); -} - -void DhcpClass::printByte(char * buf, uint8_t n ) { - char *str = &buf[1]; - buf[0]='0'; - do { - unsigned long m = n; - n /= 16; - char c = m - 16 * n; - *str-- = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); -} diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Dhcp.h b/src/DuetNG/DuetEthernet/Ethernet3/Dhcp.h deleted file mode 100644 index 8deebdd8..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Dhcp.h +++ /dev/null @@ -1,179 +0,0 @@ -// DHCP Library v0.3 - April 25, 2009 -// Author: Jordan Terrell - blog.jordanterrell.com - -#ifndef Dhcp_h -#define Dhcp_h - -#include "EthernetUdp3.h" - -/* DHCP state machine. */ -#define STATE_DHCP_START 0 -#define STATE_DHCP_DISCOVER 1 -#define STATE_DHCP_REQUEST 2 -#define STATE_DHCP_LEASED 3 -#define STATE_DHCP_REREQUEST 4 -#define STATE_DHCP_RELEASE 5 - -#define DHCP_FLAGSBROADCAST 0x8000 - -/* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 /* from server to client */ -#define DHCP_CLIENT_PORT 68 /* from client to server */ - -/* DHCP message OP code */ -#define DHCP_BOOTREQUEST 1 -#define DHCP_BOOTREPLY 2 - -/* DHCP message type */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -#define DHCP_HTYPE10MB 1 -#define DHCP_HTYPE100MB 2 - -#define DHCP_HLENETHERNET 6 -#define DHCP_HOPS 0 -#define DHCP_SECS 0 - -#define MAGIC_COOKIE 0x63825363 -#define MAX_DHCP_OPT 16 - -#define HOST_NAME "WIZnet" -#define DEFAULT_LEASE (900) //default lease time in seconds - -#define DHCP_CHECK_NONE (0) -#define DHCP_CHECK_RENEW_FAIL (1) -#define DHCP_CHECK_RENEW_OK (2) -#define DHCP_CHECK_REBIND_FAIL (3) -#define DHCP_CHECK_REBIND_OK (4) - -enum -{ - padOption = 0, - subnetMask = 1, - timerOffset = 2, - routersOnSubnet = 3, - /* timeServer = 4, - nameServer = 5,*/ - dns = 6, - /*logServer = 7, - cookieServer = 8, - lprServer = 9, - impressServer = 10, - resourceLocationServer = 11,*/ - hostName = 12, - /*bootFileSize = 13, - meritDumpFile = 14,*/ - domainName = 15, - /*swapServer = 16, - rootPath = 17, - extentionsPath = 18, - IPforwarding = 19, - nonLocalSourceRouting = 20, - policyFilter = 21, - maxDgramReasmSize = 22, - defaultIPTTL = 23, - pathMTUagingTimeout = 24, - pathMTUplateauTable = 25, - ifMTU = 26, - allSubnetsLocal = 27, - broadcastAddr = 28, - performMaskDiscovery = 29, - maskSupplier = 30, - performRouterDiscovery = 31, - routerSolicitationAddr = 32, - staticRoute = 33, - trailerEncapsulation = 34, - arpCacheTimeout = 35, - ethernetEncapsulation = 36, - tcpDefaultTTL = 37, - tcpKeepaliveInterval = 38, - tcpKeepaliveGarbage = 39, - nisDomainName = 40, - nisServers = 41, - ntpServers = 42, - vendorSpecificInfo = 43, - netBIOSnameServer = 44, - netBIOSdgramDistServer = 45, - netBIOSnodeType = 46, - netBIOSscope = 47, - xFontServer = 48, - xDisplayManager = 49,*/ - dhcpRequestedIPaddr = 50, - dhcpIPaddrLeaseTime = 51, - /*dhcpOptionOverload = 52,*/ - dhcpMessageType = 53, - dhcpServerIdentifier = 54, - dhcpParamRequest = 55, - /*dhcpMsg = 56, - dhcpMaxMsgSize = 57,*/ - dhcpT1value = 58, - dhcpT2value = 59, - /*dhcpClassIdentifier = 60,*/ - dhcpClientIdentifier = 61, - endOption = 255 -}; - -typedef struct _RIP_MSG_FIXED -{ - uint8_t op; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - uint32_t xid; - uint16_t secs; - uint16_t flags; - uint8_t ciaddr[4]; - uint8_t yiaddr[4]; - uint8_t siaddr[4]; - uint8_t giaddr[4]; - uint8_t chaddr[6]; -}RIP_MSG_FIXED; - -class DhcpClass -{ -private: - uint32_t _dhcpInitialTransactionId; - uint32_t _dhcpTransactionId; - uint8_t _dhcpMacAddr[6]; - uint8_t _dhcpLocalIp[4]; - uint8_t _dhcpSubnetMask[4]; - uint8_t _dhcpGatewayIp[4]; - uint8_t _dhcpDhcpServerIp[4]; - uint8_t _dhcpDnsServerIp[4]; - uint32_t _dhcpLeaseTime; - uint32_t _dhcpT1, _dhcpT2; - signed long _renewInSec; - signed long _rebindInSec; - signed long _lastCheck; - unsigned long _timeout; - unsigned long _responseTimeout; - unsigned long _secTimeout; - uint8_t _dhcp_state; - EthernetUDP _dhcpUdpSocket; - - int request_DHCP_lease(); - void reset_DHCP_lease(); - void presend_DHCP(); - void send_DHCP_MESSAGE(uint8_t, uint16_t); - void printByte(char *, uint8_t); - - uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); -public: - IPAddress getLocalIp(); - IPAddress getSubnetMask(); - IPAddress getGatewayIp(); - IPAddress getDhcpServerIp(); - IPAddress getDnsServerIp(); - - int beginWithDHCP(const uint8_t *macAddress, unsigned long timeout, unsigned long responseTimeout); - int checkLease(); -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Dns.cpp b/src/DuetNG/DuetEthernet/Ethernet3/Dns.cpp deleted file mode 100644 index d55fad8b..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Dns.cpp +++ /dev/null @@ -1,422 +0,0 @@ -// Arduino DNS client for WizNet5100-based Ethernet shield -// (c) Copyright 2009-2010 MCQN Ltd. -// Released under Apache License, version 2.0 - -#include "utility/w5500.h" -#include "EthernetUdp3.h" -#include "utility/util.h" - -#include "Dns.h" -#include <cstring> -#include "Core.h" - - -#define SOCKET_NONE 255 -// Various flags and header field values for a DNS message -#define UDP_HEADER_SIZE 8 -#define DNS_HEADER_SIZE 12 -#define TTL_SIZE 4 -#define QUERY_FLAG (0) -#define RESPONSE_FLAG (1<<15) -#define QUERY_RESPONSE_MASK (1<<15) -#define OPCODE_STANDARD_QUERY (0) -#define OPCODE_INVERSE_QUERY (1<<11) -#define OPCODE_STATUS_REQUEST (2<<11) -#define OPCODE_MASK (15<<11) -#define AUTHORITATIVE_FLAG (1<<10) -#define TRUNCATION_FLAG (1<<9) -#define RECURSION_DESIRED_FLAG (1<<8) -#define RECURSION_AVAILABLE_FLAG (1<<7) -#define RESP_NO_ERROR (0) -#define RESP_FORMAT_ERROR (1) -#define RESP_SERVER_FAILURE (2) -#define RESP_NAME_ERROR (3) -#define RESP_NOT_IMPLEMENTED (4) -#define RESP_REFUSED (5) -#define RESP_MASK (15) -#define TYPE_A (0x0001) -#define CLASS_IN (0x0001) -#define LABEL_COMPRESSION_MASK (0xC0) -// Port number that DNS servers listen on -#define DNS_PORT 53 - -// Possible return codes from ProcessResponse -#define SUCCESS 1 -#define TIMED_OUT -1 -#define INVALID_SERVER -2 -#define TRUNCATED -3 -#define INVALID_RESPONSE -4 - -void DNSClient::begin(const IPAddress& aDNSServer) -{ - iDNSServer = aDNSServer; - iRequestId = 0; -} - - -int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) -{ - // See if we've been given a valid IP address - const char* p =aIPAddrString; - while (*p && - ( (*p == '.') || (*p >= '0') || (*p <= '9') )) - { - p++; - } - - if (*p == '\0') - { - // It's looking promising, we haven't found any invalid characters - p = aIPAddrString; - int segment =0; - int segmentValue =0; - while (*p && (segment < 4)) - { - if (*p == '.') - { - // We've reached the end of a segment - if (segmentValue > 255) - { - // You can't have IP address segments that don't fit in a byte - return 0; - } - else - { - aResult[segment] = (byte)segmentValue; - segment++; - segmentValue = 0; - } - } - else - { - // Next digit - segmentValue = (segmentValue*10)+(*p - '0'); - } - p++; - } - // We've reached the end of address, but there'll still be the last - // segment to deal with - if ((segmentValue > 255) || (segment > 3)) - { - // You can't have IP address segments that don't fit in a byte, - // or more than four segments - return 0; - } - else - { - aResult[segment] = (byte)segmentValue; - return 1; - } - } - else - { - return 0; - } -} - -int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) -{ - int ret =0; - - // See if it's a numeric IP address - if (inet_aton(aHostname, aResult)) - { - // It is, our work here is done - return 1; - } - - // Check we've got a valid DNS server to use - if (iDNSServer == INADDR_NONE) - { - return INVALID_SERVER; - } - - // Find a socket to use - if (iUdp.begin(1024+(millis() & 0xF)) == 1) - { - // Try up to three times - int retries = 0; -// while ((retries < 3) && (ret <= 0)) - { - // Send DNS request - ret = iUdp.beginPacket(iDNSServer, DNS_PORT); - if (ret != 0) - { - // Now output the request data - ret = BuildRequest(aHostname); - if (ret != 0) - { - // And finally send the request - ret = iUdp.endPacket(); - if (ret != 0) - { - // Now wait for a response - int wait_retries = 0; - ret = TIMED_OUT; - while ((wait_retries < 3) && (ret == TIMED_OUT)) - { - ret = ProcessResponse(5000, aResult); - wait_retries++; - } - } - } - } - retries++; - } - - // We're done with the socket now - iUdp.stop(); - } - - return ret; -} - -uint16_t DNSClient::BuildRequest(const char* aName) -{ - // Build header - // 1 1 1 1 1 1 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // | ID | - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // | QDCOUNT | - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // | ANCOUNT | - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // | NSCOUNT | - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // | ARCOUNT | - // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - // As we only support one request at a time at present, we can simplify - // some of this header - iRequestId = millis(); // generate a random ID - uint16_t twoByteBuffer; - - // FIXME We should also check that there's enough space available to write to, rather - // FIXME than assume there's enough space (as the code does at present) - iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); - - twoByteBuffer = htons((uint16_t)(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG)); - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - - twoByteBuffer = htons(1); // One question record - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - - twoByteBuffer = 0; // Zero answer records - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - // and zero additional records - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - - // Build question - const char* start =aName; - const char* end =start; - uint8_t len; - // Run through the name being requested - while (*end) - { - // Find out how long this section of the name is - end = start; - while (*end && (*end != '.') ) - { - end++; - } - - if (end-start > 0) - { - // Write out the size of this section - len = end-start; - iUdp.write(&len, sizeof(len)); - // And then write out the section - iUdp.write((uint8_t*)start, end-start); - } - start = end+1; - } - - // We've got to the end of the question name, so - // terminate it with a zero-length section - len = 0; - iUdp.write(&len, sizeof(len)); - // Finally the type and class of question - twoByteBuffer = htons(TYPE_A); - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - - twoByteBuffer = htons(CLASS_IN); // Internet class of question - iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); - // Success! Everything buffered okay - return 1; -} - - -uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) -{ - uint32_t startTime = millis(); - - // Wait for a response packet - while(iUdp.parsePacket() <= 0) - { - if((millis() - startTime) > aTimeout) - return TIMED_OUT; - delay(50); - } - - // We've had a reply! - // Read the UDP header - uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header - // Check that it's a response from the right server and the right port - if ( (iDNSServer != iUdp.remoteIP()) || - (iUdp.remotePort() != DNS_PORT) ) - { - // It's not from who we expected - return INVALID_SERVER; - } - - // Read through the rest of the response - if (iUdp.available() < DNS_HEADER_SIZE) - { - return TRUNCATED; - } - iUdp.read(header, DNS_HEADER_SIZE); - - uint16_t header_flags = get16nb(&header[2]); - // Check that it's a response to this request - if ( ( iRequestId != get16(&header[0]) ) || - ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) - { - // Mark the entire packet as read - iUdp.flush(); - return INVALID_RESPONSE; - } - // Check for any errors in the response (or in our request) - // although we don't do anything to get round these - if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) - { - // Mark the entire packet as read - iUdp.flush(); - return -5; //INVALID_RESPONSE; - } - - // And make sure we've got (at least) one answer - uint16_t answerCount = get16nb(&header[6]); - if (answerCount == 0 ) - { - // Mark the entire packet as read - iUdp.flush(); - return -6; //INVALID_RESPONSE; - } - - // Skip over any questions - for (uint16_t i = 0; i < get16nb(&header[4]); i++) - { - // Skip over the name - uint8_t len; - do - { - iUdp.read(&len, sizeof(len)); - if (len > 0) - { - // Don't need to actually read the data out for the string, just - // advance ptr to beyond it - while(len--) - { - iUdp.read(); // we don't care about the returned byte - } - } - } while (len != 0); - - // Now jump over the type and class - for (int i =0; i < 4; i++) - { - iUdp.read(); // we don't care about the returned byte - } - } - - // Now we're up to the bit we're interested in, the answer - // There might be more than one answer (although we'll just use the first - // type A answer) and some authority and additional resource records but - // we're going to ignore all of them. - - for (uint16_t i =0; i < answerCount; i++) - { - // Skip the name - uint8_t len; - do - { - iUdp.read(&len, sizeof(len)); - if ((len & LABEL_COMPRESSION_MASK) == 0) - { - // It's just a normal label - if (len > 0) - { - // And it's got a length - // Don't need to actually read the data out for the string, - // just advance ptr to beyond it - while(len--) - { - iUdp.read(); // we don't care about the returned byte - } - } - } - else - { - // This is a pointer to a somewhere else in the message for the - // rest of the name. We don't care about the name, and RFC1035 - // says that a name is either a sequence of labels ended with a - // 0 length octet or a pointer or a sequence of labels ending in - // a pointer. Either way, when we get here we're at the end of - // the name - // Skip over the pointer - iUdp.read(); // we don't care about the returned byte - // And set len so that we drop out of the name loop - len = 0; - } - } while (len != 0); - - // Check the type and class - uint16_t answerType; - uint16_t answerClass; - iUdp.read((uint8_t*)&answerType, sizeof(answerType)); - iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); - - // Ignore the Time-To-Live as we don't do any caching - for (int i =0; i < TTL_SIZE; i++) - { - iUdp.read(); // we don't care about the returned byte - } - - // And read out the length of this answer - // Don't need header_flags anymore, so we can reuse it here - iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); - - if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) - { - if (htons(header_flags) != 4) - { - // It's a weird size - // Mark the entire packet as read - iUdp.flush(); - return -9;//INVALID_RESPONSE; - } - iUdp.read(aAddress.raw_address(), 4); - return SUCCESS; - } - else - { - // This isn't an answer type we're after, move onto the next one - for (uint16_t i =0; i < htons(header_flags); i++) - { - iUdp.read(); // we don't care about the returned byte - } - } - } - - // Mark the entire packet as read - iUdp.flush(); - - // If we get here then we haven't found an answer - return -10;//INVALID_RESPONSE; -} - diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Dns.h b/src/DuetNG/DuetEthernet/Ethernet3/Dns.h deleted file mode 100644 index 481c5c40..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Dns.h +++ /dev/null @@ -1,41 +0,0 @@ -// Arduino DNS client for WizNet5100-based Ethernet shield -// (c) Copyright 2009-2010 MCQN Ltd. -// Released under Apache License, version 2.0 - -#ifndef DNSClient_h -#define DNSClient_h - -#include <EthernetUdp3.h> - -class DNSClient -{ -public: - // ctor - void begin(const IPAddress& aDNSServer); - - /** Convert a numeric IP address string into a four-byte IP address. - @param aIPAddrString IP address to convert - @param aResult IPAddress structure to store the returned IP address - @result 1 if aIPAddrString was successfully converted to an IP address, - else error code - */ - int inet_aton(const char *aIPAddrString, IPAddress& aResult); - - /** Resolve the given hostname to an IP address. - @param aHostname Name to be resolved - @param aResult IPAddress structure to store the returned IP address - @result 1 if aIPAddrString was successfully converted to an IP address, - else error code - */ - int getHostByName(const char* aHostname, IPAddress& aResult); - -protected: - uint16_t BuildRequest(const char* aName); - uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); - - IPAddress iDNSServer; - uint16_t iRequestId; - EthernetUDP iUdp; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Ethernet3.cpp b/src/DuetNG/DuetEthernet/Ethernet3/Ethernet3.cpp deleted file mode 100644 index d8a2b9c7..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Ethernet3.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) - -- 10 Apr. 2015 - Added support for Arduino Ethernet Shield 2 - by Arduino.org team - - */ - -#include "Ethernet3.h" -#include "Dhcp.h" - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) - -// XXX: don't make assumptions about the value of MAX_SOCK_NUM. -uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { 0, }; -uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { 0, }; - - -int EthernetClass::begin(const uint8_t *mac_address, unsigned long timeout, unsigned long responseTimeout) -{ - if (_dhcp == nullptr) - { - _dhcp = new DhcpClass(); - } - - // Initialise the basic info - w5500.init(); - w5500.setMACAddress(mac_address); - w5500.setIPAddress(IPAddress(0,0,0,0).raw_address()); - - // Now try to get our config info from a DHCP server - const int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); - if (ret == 1) - { - // We've successfully found a DHCP server and got our configuration info, so set things accordingly - w5500.setIPAddress(_dhcp->getLocalIp().raw_address()); - w5500.setGatewayIp(_dhcp->getGatewayIp().raw_address()); - w5500.setSubnetMask(_dhcp->getSubnetMask().raw_address()); - _dnsServerAddress = _dhcp->getDnsServerIp(); - } - - return ret; -} - -void EthernetClass::begin(const uint8_t *mac_address, IPAddress local_ip) -{ - IPAddress subnet(255, 255, 255, 0); - begin(mac_address, local_ip, subnet); -} - -void EthernetClass::begin(const uint8_t *mac_address, IPAddress local_ip, IPAddress subnet) -{ - // Assume the gateway will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress gateway = local_ip; - gateway[3] = 1; - begin(mac_address, local_ip, subnet, gateway); -} - -void EthernetClass::begin(const uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway) -{ - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns_server = local_ip; - dns_server[3] = 1; - begin(mac_address, local_ip, subnet, gateway, dns_server); -} - -void EthernetClass::begin(const uint8_t *mac, IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) -{ - w5500.init(); - w5500.setMACAddress(mac); - w5500.setIPAddress(local_ip.raw_address()); - w5500.setGatewayIp(gateway.raw_address()); - w5500.setSubnetMask(subnet.raw_address()); - _dnsServerAddress = dns_server; -} - -void EthernetClass::stop() -{ - w5500.stop(); -} - -int EthernetClass::maintain(){ - int rc = DHCP_CHECK_NONE; - if(_dhcp != NULL){ - //we have a pointer to dhcp, use it - rc = _dhcp->checkLease(); - switch ( rc ){ - case DHCP_CHECK_NONE: - //nothing done - break; - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //we might have got a new IP. - w5500.setIPAddress(_dhcp->getLocalIp().raw_address()); - w5500.setGatewayIp(_dhcp->getGatewayIp().raw_address()); - w5500.setSubnetMask(_dhcp->getSubnetMask().raw_address()); - _dnsServerAddress = _dhcp->getDnsServerIp(); - break; - default: - //this is actually a error, it will retry though - break; - } - } - return rc; -} - -uint8_t EthernetClass::phyState() { - return w5500.getPHYCFGR(); - } - -uint8_t EthernetClass::link() { - return bitRead(w5500.getPHYCFGR(), 0); - } - -const char* EthernetClass::linkReport() { - if(bitRead(w5500.getPHYCFGR(), 0) == 1) return "LINK"; - else return "NO LINK"; - } - -uint8_t EthernetClass::speed() { - if(bitRead(w5500.getPHYCFGR(), 0) == 1) { - if(bitRead(w5500.getPHYCFGR(), 1) == 1) return 100; - if(bitRead(w5500.getPHYCFGR(), 1) == 0) return 10; - } - return 0; - } - -const char* EthernetClass::speedReport() { - if(bitRead(w5500.getPHYCFGR(), 0) == 1) { - if(bitRead(w5500.getPHYCFGR(), 1) == 1) return "100 MB"; - if(bitRead(w5500.getPHYCFGR(), 1) == 0) return "10 MB"; - } - return "NO LINK"; - } - -uint8_t EthernetClass::duplex() { - if(bitRead(w5500.getPHYCFGR(), 0) == 1) { - if(bitRead(w5500.getPHYCFGR(), 2) == 1) return 2; - if(bitRead(w5500.getPHYCFGR(), 2) == 0) return 1; - } - return 0; - } - -const char* EthernetClass::duplexReport() { - if(bitRead(w5500.getPHYCFGR(), 0) == 1) { - if(bitRead(w5500.getPHYCFGR(), 2) == 1) return "FULL DUPLEX"; - if(bitRead(w5500.getPHYCFGR(), 2) == 0) return "HALF DUPLEX"; - } - return "NO LINK"; - } - -void EthernetClass::macAddress(uint8_t mac[]) { - w5500.getMACAddress(mac); - } - -const char* EthernetClass::macAddressReport() { - uint8_t mac[6]; - static char str[18]; - w5500.getMACAddress(mac); - sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return str; - } - -IPAddress EthernetClass::localIP() -{ - IPAddress ret; - w5500.getIPAddress(ret.raw_address()); - return ret; -} - -IPAddress EthernetClass::subnetMask() -{ - IPAddress ret; - w5500.getSubnetMask(ret.raw_address()); - return ret; -} - -IPAddress EthernetClass::gatewayIP() -{ - IPAddress ret; - w5500.getGatewayIp(ret.raw_address()); - return ret; -} - -IPAddress EthernetClass::dnsServerIP() -{ - return _dnsServerAddress; -} - -EthernetClass Ethernet; diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Ethernet3.h b/src/DuetNG/DuetEthernet/Ethernet3/Ethernet3.h deleted file mode 100644 index 0e176c1b..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Ethernet3.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) - - - 10 Apr. 2015 - Added support for Arduino Ethernet Shield 2 - by Arduino.org team - - */ -#ifndef ethernet3_h -#define ethernet3_h - -#include <inttypes.h> -#include "utility/w5500.h" -#include "IPAddress.h" -#include "EthernetClient.h" -#include "EthernetServer.h" -#include "Dhcp.h" - - -class EthernetClass { -private: - IPAddress _dnsServerAddress; - DhcpClass* _dhcp; -public: - static uint8_t _state[MAX_SOCK_NUM]; - static uint16_t _server_port[MAX_SOCK_NUM]; - - // Initialize the Ethernet shield to use the provided MAC address and gain the rest of the configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(const uint8_t *mac_address, unsigned long timeout, unsigned long responseTimeout); - void begin(const uint8_t *mac_address, IPAddress local_ip); - void begin(const uint8_t *mac_address, IPAddress local_ip, IPAddress subnet); - void begin(const uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway); - void begin(const uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); - - int maintain(); - - void stop(); - - uint8_t phyState(); // returns the PHYCFGR - uint8_t link(); // returns the linkstate, 1 = linked, 0 = no link - const char* linkReport(); // returns the linkstate as a string - uint8_t speed(); // returns speed in MB/s - const char* speedReport(); // returns speed as a string - uint8_t duplex(); // returns duplex mode 0 = no link, 1 = Half Duplex, 2 = Full Duplex - const char* duplexReport(); // returns duplex mode as a string - - void macAddress(uint8_t mac[]); // get the MAC Address - const char* macAddressReport(); // returns the the MAC Address as a string - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - - friend class EthernetClient; - friend class EthernetServer; -}; - -extern EthernetClass Ethernet; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/EthernetClient.cpp b/src/DuetNG/DuetEthernet/Ethernet3/EthernetClient.cpp deleted file mode 100644 index 2cb38e60..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/EthernetClient.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "utility/w5500.h" -#include "utility/socket.h" - -#include "cstring" - - -#include "Core.h" - -#include "Ethernet3.h" -#include "EthernetClient.h" -#include "EthernetServer.h" -#include "Dns.h" - -uint16_t EthernetClient::_srcport = 1024; - -EthernetClient::EthernetClient() : _sock(MAX_SOCK_NUM) { -} - -EthernetClient::EthernetClient(uint8_t sock) : _sock(sock) { -} - -int EthernetClient::connect(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); - if (ret == 1) { - return connect(remote_addr, port); - } else { - return ret; - } -} - -int EthernetClient::connect(IPAddress ip, uint16_t port) { - if (_sock != MAX_SOCK_NUM) - return 0; - - for (int i = 0; i < MAX_SOCK_NUM; i++) { - uint8_t s = w5500.readSnSR(i); - if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { - _sock = i; - break; - } - } - - if (_sock == MAX_SOCK_NUM) - return 0; - - _srcport++; - if (_srcport == 0) _srcport = 1024; - socket(_sock, SnMR::TCP, _srcport, 0); - - if (!::connect(_sock, rawIPAddress(ip), port)) { - _sock = MAX_SOCK_NUM; - return 0; - } - - while (status() != SnSR::ESTABLISHED) { - delay(1); - if (status() == SnSR::CLOSED) { - _sock = MAX_SOCK_NUM; - return 0; - } - } - - return 1; -} - -size_t EthernetClient::write(uint8_t b) { - return write(&b, 1); -} - -size_t EthernetClient::write(const uint8_t *buf, size_t size) { - if (_sock == MAX_SOCK_NUM) { - setWriteError(); - return 0; - } - if (!send(_sock, buf, size)) { - setWriteError(); - return 0; - } - return size; -} - -int EthernetClient::available() { - if (_sock != MAX_SOCK_NUM) - return w5500.getRXReceivedSize(_sock); - return 0; -} - -int EthernetClient::read() { - uint8_t b; - if ( recv(_sock, &b, 1) > 0 ) - { - // recv worked - return b; - } - else - { - // No data available - return -1; - } -} - -int EthernetClient::read(uint8_t *buf, size_t size) { - return recv(_sock, buf, size); -} - -int EthernetClient::peek() { - uint8_t b; - // Unlike recv, peek doesn't check to see if there's any data available, so we must - if (!available()) - return -1; - ::peek(_sock, &b); - return b; -} - -void EthernetClient::flush() { - ::flush(_sock); -} - -void EthernetClient::stop() { - if (_sock == MAX_SOCK_NUM) - return; - - // attempt to close the connection gracefully (send a FIN to other side) - disconnect(_sock); - unsigned long start = millis(); - - // wait a second for the connection to close - while (status() != SnSR::CLOSED && millis() - start < 1000) - delay(1); - - // if it hasn't closed, close it forcefully - if (status() != SnSR::CLOSED) - close(_sock); - - EthernetClass::_server_port[_sock] = 0; - _sock = MAX_SOCK_NUM; -} - -uint8_t EthernetClient::connected() { - if (_sock == MAX_SOCK_NUM) return 0; - - uint8_t s = status(); - return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT || - (s == SnSR::CLOSE_WAIT && !available())); -} - -uint8_t EthernetClient::status() { - if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED; - return w5500.readSnSR(_sock); -} - -// the next function allows us to use the client returned by -// EthernetServer::available() as the condition in an if-statement. - -EthernetClient::operator bool() { - return _sock != MAX_SOCK_NUM; -} - -bool EthernetClient::operator==(const EthernetClient& rhs) { - return _sock == rhs._sock && _sock != MAX_SOCK_NUM && rhs._sock != MAX_SOCK_NUM; -} diff --git a/src/DuetNG/DuetEthernet/Ethernet3/EthernetClient.h b/src/DuetNG/DuetEthernet/Ethernet3/EthernetClient.h deleted file mode 100644 index 8612e5c1..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/EthernetClient.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef ethernetclient_h -#define ethernetclient_h -#include "Core.h" -#include "Print.h" -#include "Client.h" -#include "IPAddress.h" - -class EthernetClient : public Client { - -public: - EthernetClient(); - EthernetClient(uint8_t sock); - - uint8_t status(); - virtual int connect(IPAddress ip, uint16_t port); - virtual int connect(const char *host, uint16_t port); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual int available(); - virtual int read(); - virtual int read(uint8_t *buf, size_t size); - virtual int peek(); - virtual void flush(); - virtual void stop(); - virtual uint8_t connected(); - virtual operator bool(); - virtual bool operator==(const EthernetClient&); - virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; - - friend class EthernetServer; - - using Print::write; - -private: - static uint16_t _srcport; - uint8_t _sock; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/EthernetServer.cpp b/src/DuetNG/DuetEthernet/Ethernet3/EthernetServer.cpp deleted file mode 100644 index 406f0b3f..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/EthernetServer.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "utility/w5500.h" -#include "utility/socket.h" -extern "C" { -#include "string.h" -} - -#include "Ethernet3.h" -#include "EthernetClient.h" -#include "EthernetServer.h" - -EthernetServer::EthernetServer(uint16_t port) -{ - _port = port; -} - -void EthernetServer::begin() -{ - for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { - EthernetClient client(sock); - if (client.status() == SnSR::CLOSED) { - socket(sock, SnMR::TCP, _port, 0); - listen(sock); - EthernetClass::_server_port[sock] = _port; - break; - } - } -} - -void EthernetServer::accept() -{ - int listening = 0; - - for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { - EthernetClient client(sock); - - if (EthernetClass::_server_port[sock] == _port) { - if (client.status() == SnSR::LISTEN) { - listening = 1; - } - else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) { - client.stop(); - } - } - } - - if (!listening) { - begin(); - } -} - -EthernetClient EthernetServer::available() -{ - accept(); - - for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { - EthernetClient client(sock); - if (EthernetClass::_server_port[sock] == _port && - (client.status() == SnSR::ESTABLISHED || - client.status() == SnSR::CLOSE_WAIT)) { - if (client.available()) { - // XXX: don't always pick the lowest numbered socket. - return client; - } - } - } - - return EthernetClient(MAX_SOCK_NUM); -} - -size_t EthernetServer::write(uint8_t b) -{ - return write(&b, 1); -} - -size_t EthernetServer::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - - accept(); - - for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { - EthernetClient client(sock); - - if (EthernetClass::_server_port[sock] == _port && - client.status() == SnSR::ESTABLISHED) { - n += client.write(buffer, size); - } - } - - return n; -} diff --git a/src/DuetNG/DuetEthernet/Ethernet3/EthernetServer.h b/src/DuetNG/DuetEthernet/Ethernet3/EthernetServer.h deleted file mode 100644 index 86ccafe9..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/EthernetServer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef ethernetserver_h -#define ethernetserver_h - -#include "Server.h" - -class EthernetClient; - -class EthernetServer : -public Server { -private: - uint16_t _port; - void accept(); -public: - EthernetServer(uint16_t); - EthernetClient available(); - virtual void begin(); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - using Print::write; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/EthernetUdp3.cpp b/src/DuetNG/DuetEthernet/Ethernet3/EthernetUdp3.cpp deleted file mode 100644 index a8ad13ee..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/EthernetUdp3.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. - * This version only offers minimal wrapping of socket.c/socket.h - * Drop Udp.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 - * - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - */ - -#include "utility/w5500.h" -#include "utility/socket.h" -#include "Ethernet3.h" -#include "Udp.h" -#include "Dns.h" - -#undef UDP - -/* Constructor */ -EthernetUDP::EthernetUDP() : _sock(MAX_SOCK_NUM) {} - -/* Start EthernetUDP socket, listening at local port PORT */ -uint8_t EthernetUDP::begin(uint16_t port) -{ - if (_sock != MAX_SOCK_NUM) - { - return 0; - } - - for (int i = 0; i < MAX_SOCK_NUM; i++) - { - uint8_t s = w5500.readSnSR(i); - if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) - { - _sock = i; - break; - } - } - - if (_sock == MAX_SOCK_NUM) - { - return 0; - } - - _port = port; - _remaining = 0; - socket(_sock, SnMR::UDP, _port, 0); - - return 1; -} - -/* return number of bytes available in the current packet, - will return zero if parsePacket hasn't been called yet */ -int EthernetUDP::available() -{ - return _remaining; -} - -/* Release any resources being used by this EthernetUDP instance */ -void EthernetUDP::stop() -{ - if (_sock == MAX_SOCK_NUM) - { - return; - } - - close(_sock); - - EthernetClass::_server_port[_sock] = 0; - _sock = MAX_SOCK_NUM; -} - -int EthernetUDP::beginPacket(const char *host, uint16_t port) -{ - // Look up the host first - DNSClient dns; - IPAddress remote_addr; - - dns.begin(Ethernet.dnsServerIP()); - const int ret = dns.getHostByName(host, remote_addr); - if (ret == 1) - { - return beginPacket(remote_addr, port); - } - else - { - return ret; - } -} - -int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) -{ - _offset = 0; - return startUDP(_sock, rawIPAddress(ip), port); -} - -int EthernetUDP::endPacket() -{ - return sendUDP(_sock); -} - -size_t EthernetUDP::write(uint8_t byte) -{ - return write(&byte, 1); -} - -size_t EthernetUDP::write(const uint8_t *buffer, size_t size) -{ - uint16_t bytes_written = bufferData(_sock, _offset, buffer, size); - _offset += bytes_written; - return bytes_written; -} - -int EthernetUDP::parsePacket() -{ - // discard any remaining bytes in the last packet - flush(); - - if (w5500.getRXReceivedSize(_sock) > 0) - { - //HACK - hand-parse the UDP packet using TCP recv method - uint8_t tmpBuf[8]; - //read 8 header bytes and get IP and port from it - int ret = recv(_sock, tmpBuf, 8); - if (ret > 0) - { - _remoteIP = tmpBuf; - _remotePort = tmpBuf[4]; - _remotePort = (_remotePort << 8) + tmpBuf[5]; - _remaining = tmpBuf[6]; - _remaining = (_remaining << 8) + tmpBuf[7]; - - // When we get here, any remaining bytes are the data - ret = _remaining; - } - return ret; - } - // There aren't any packets available - return 0; -} - -int EthernetUDP::read() -{ - uint8_t byte; - - if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0)) - { - // We read things without any problems - _remaining--; - return byte; - } - - // If we get here, there's no data available - return -1; -} - -int EthernetUDP::read(unsigned char* buffer, size_t len) -{ - if (_remaining > 0) - { - int got; - if (_remaining <= len) - { - // data should fit in the buffer - got = recv(_sock, buffer, _remaining); - } - else - { - // too much data for the buffer, - // grab as much as will fit - got = recv(_sock, buffer, len); - } - - if (got > 0) - { - _remaining -= got; - return got; - } - } - - // If we get here, there's no data available or recv failed - return -1; -} - -int EthernetUDP::peek() -{ - uint8_t b; - // Unlike recv, peek doesn't check to see if there's any data available, so we must. - // If the user hasn't called parsePacket yet then return nothing otherwise they - // may get the UDP header - if (!_remaining) - { - return -1; - } - ::peek(_sock, &b); - return b; -} - -void EthernetUDP::flush() -{ - // could this fail (loop endlessly) if _remaining > 0 and recv in read fails? - // should only occur if recv fails after telling us the data is there, lets - // hope the w5500 always behaves :) - while (_remaining) - { - read(); - } -} - -/* Start EthernetUDP socket, listening at local port PORT */ -uint8_t EthernetUDP::beginMulticast(IPAddress ip, uint16_t port) -{ - if (_sock != MAX_SOCK_NUM) - { - return 0; - } - - for (int i = 0; i < MAX_SOCK_NUM; i++) - { - const uint8_t s = w5500.readSnSR(i); - if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) - { - _sock = i; - break; - } - } - - if (_sock == MAX_SOCK_NUM) - { - return 0; - } - - // Calculate MAC address from Multicast IP Address - byte mac[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; - - mac[3] = ip[1] & 0x7F; - mac[4] = ip[2]; - mac[5] = ip[3]; - - w5500.writeSnDIPR(_sock, rawIPAddress(ip)); //239.255.0.1 - w5500.writeSnDPORT(_sock, port); - w5500.writeSnDHAR(_sock,mac); - - _remaining = 0; - socket(_sock, SnMR::UDP, port, SnMR::MULTI); - return 1; -} - -// End diff --git a/src/DuetNG/DuetEthernet/Ethernet3/EthernetUdp3.h b/src/DuetNG/DuetEthernet/Ethernet3/EthernetUdp3.h deleted file mode 100644 index 41676bb8..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/EthernetUdp3.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. - * This version only offers minimal wrapping of socket.c/socket.h - * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * 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 - * - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - * - */ - - -#ifndef ethernetudp3_h -#define ethernetudp3_h - -#include <Udp.h> - -#define UDP_TX_PACKET_MAX_SIZE 24 - -class EthernetUDP : public UdpStream { -private: - uint8_t _sock; // socket ID for Wiz5100 - uint16_t _port; // local port to listen on - IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed - uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed - uint16_t _offset; // offset into the packet being sent - uint16_t _remaining; // remaining bytes of incoming packet yet to be processed - -public: - EthernetUDP(); // Constructor - virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop(); // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port); - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port); - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket(); - // Write a single byte into the packet - virtual size_t write(uint8_t); - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size); - - using Print::write; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket(); - // Number of bytes remaining in the current packet - virtual int available(); - // Read a single byte from the current packet - virtual int read(); - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len); - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek(); - virtual void flush(); // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() { return _remoteIP; }; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() { return _remotePort; }; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/README.md b/src/DuetNG/DuetEthernet/Ethernet3/README.md deleted file mode 100644 index 37c06aa8..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Ethernet3 -Ethernet library for Arduino and Ethernetshield2 / WIZ550io / WIZ850io with Wiznet W5500 chip -based on the Ethernet2 library of arduino.org - -added some new functionalities - -you need to include - - #include <Ethernet3.h> // instead Ethernet.h - #include <EthernetUdp3.h> // instead EthernetUdp.h for UDP functionality - -###- New init procedure **!!!** - -the init of the Ethernetinterface changed, the ordner is now: - -*mac, ip, subnet, gateway, dns* instead *mac, ip, dns, gateway, subnet*, -which is more logical - - Ethernet.begin(mac, ip, subnet, gateway, dns); - -###- Multicast support - -multicast for udp added - - EthernetUdp udp - upd.beginMulticast(multicastIP, port); - -###- PHY support - -added some function to read the PHYCFGR in Ethernet3 - - uint8_t phyState(); // returns the PHYCFGR - uint8_t link(); // returns the linkstate, 1 = linked, 0 = no link - const char* linkReport(); // returns the linkstate as a string - uint8_t speed(); // returns speed in MB/s - const char* speedReport(); // returns speed as a string - uint8_t duplex(); // returns duplex mode 0 = no link, 1 = Half Duplex, 2 = Full Duplex - const char* duplexReport(); // returns duplex mode as a string - -example - - Serial.println(Ethernet.linkReport()); - -###- MAC address - -added some function to read the MAC address in Ethernet3, this is helpfull when you use Wiznet boards like WIZ550io with build in MAC address - - void macAddress(uint8_t mac[]); // get the MAC Address - const char* macAddressReport(); // returns the the MAC Address as a string - -example - - uint8_t mac[6]; // array for mac address - Ethernet.macAddress(mac); diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Server.h b/src/DuetNG/DuetEthernet/Ethernet3/Server.h deleted file mode 100644 index 69e3e39f..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Server.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Server.h - Base class that provides Server - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef server_h -#define server_h - -#include "Print.h" - -class Server : public Print { -public: - virtual void begin() =0; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Twitter.cpp b/src/DuetNG/DuetEthernet/Ethernet3/Twitter.cpp deleted file mode 100644 index 7d1b9a9c..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Twitter.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - Twitter.cpp - Arduino library to Post messages to Twitter using OAuth. - Copyright (c) NeoCat 2010-2011. All right reserved. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -// ver1.2 - Use <string.h> -// ver1.3 - Support IDE 1.0 - -#include <cstring> -#include "Twitter.h" - -#define LIB_DOMAIN "arduino-tweet.appspot.com" - -Twitter::Twitter(const char *token) : token(token) -{ -} - -bool Twitter::doPost(const char *msg) -{ - parseStatus = 0; - statusCode = 0; - if (client.connect(LIB_DOMAIN, 80)) { - client.println("POST http://" LIB_DOMAIN "/update HTTP/1.0"); - client.print("Content-Length: "); - client.println(strlen(msg)+strlen(token)+14); - client.println(); - client.print("token="); - client.print(token); - client.print("&status="); - client.println(msg); - } else { - return false; - } - return true; -} - -bool Twitter::checkStatus(Print *debug) -{ - if (!client.connected()) { - if (debug) - while(client.available()) - debug->print((char)client.read()); - client.flush(); - client.stop(); - return false; - } - if (!client.available()) - return true; - char c = client.read(); - if (debug) - debug->print(c); - switch(parseStatus) { - case 0: - if (c == ' ') parseStatus++; break; // skip "HTTP/1.1 " - case 1: - if (c >= '0' && c <= '9') { - statusCode *= 10; - statusCode += c - '0'; - } else { - parseStatus++; - } - } - return true; -} - -int Twitter::wait(Print *debug) -{ - while (checkStatus(debug)); - return statusCode; -} diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Twitter.h b/src/DuetNG/DuetEthernet/Ethernet3/Twitter.h deleted file mode 100644 index 80c5673b..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Twitter.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Twitter.cpp - Arduino library to Post messages to Twitter using OAuth. - Copyright (c) NeoCat 2010-2011. All right reserved. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -// ver1.2 - Use <Udp.h> to support IDE 0019 or later -// ver1.3 - Support IDE 1.0 - -#ifndef TWITTER_H -#define TWITTER_H - -#include <inttypes.h> -#include <Ethernet3.h> - -class Twitter -{ -private: - uint8_t parseStatus; - int statusCode; - const char *token; - EthernetClient client; -public: - Twitter(const char *user_and_passwd); - - bool doPost(const char *msg); - bool checkStatus(Print *debug = NULL); - int wait(Print *debug = NULL); - int status(void) { return statusCode; } -}; - -#endif //TWITTER_H diff --git a/src/DuetNG/DuetEthernet/Ethernet3/Udp.h b/src/DuetNG/DuetEthernet/Ethernet3/Udp.h deleted file mode 100644 index 04207c71..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/Udp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Udp.cpp: Library to send/receive UDP packets. - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * 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 udp_h -#define udp_h - -#include <Stream.h> -#include <IPAddress.h> - -class UdpStream : public Stream { - -public: - virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop() =0; // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) =0; - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port) =0; - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket() =0; - // Write a single byte into the packet - virtual size_t write(uint8_t) =0; - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size) =0; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket() =0; - // Number of bytes remaining in the current packet - virtual int available() =0; - // Read a single byte from the current packet - virtual int read() =0; - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len) =0; - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) =0; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek() =0; - virtual void flush() =0; // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() =0; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() =0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/WizSpi.cpp b/src/DuetNG/DuetEthernet/Ethernet3/utility/WizSpi.cpp deleted file mode 100644 index 076017f9..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/WizSpi.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* - * WizSpi.cpp - * - * Created on: 16 Dec 2016 - * Author: David - */ - -#include "WizSpi.h" -#include "variant.h" -#include "Pins.h" - -// Define exactly one of the following as 1, the other as zero -// The PDC seems to be too slow to work reliably without getting transmit underruns, so we use the DMAC now. -#define USE_PDC 0 // use peripheral DMA controller -#define USE_DMAC 0 // use general DMA controller - -#if USE_PDC -#include "pdc.h" -#endif - -#if USE_DMAC -#include "dmac.h" -#endif - -#include "matrix.h" - -// Functions called by the W5500 module to transfer data to/from the W5500 via SPI -const uint32_t SpiClockFrequency = 10000000; // use 10MHz for now, increase it later -const unsigned int SpiPeripheralChannelId = 0; // we use NPCS0 as the slave select signal - -#if USE_PDC -static Pdc *spi_pdc; -static inline void spi_rx_dma_enable() -{ - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN); -} - -static inline void spi_tx_dma_enable() -{ - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN); -} - -static inline void spi_rx_dma_disable() -{ - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS); -} - -static inline void spi_tx_dma_disable() -{ - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS); -} - -static bool spi_dma_check_rx_complete() -{ - return true; -} - -static void spi_tx_dma_setup(const TransactionBuffer *buf, uint32_t maxTransmitLength) -{ - pdc_packet_t pdc_spi_packet; - pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); - pdc_spi_packet.ul_size = buf->PacketLength() * 4; // need length in bytes - pdc_tx_init(spi_pdc, &pdc_spi_packet, NULL); -} - -static void spi_rx_dma_setup(const TransactionBuffer *buf) -{ - pdc_packet_t pdc_spi_packet; - pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); - pdc_spi_packet.ul_size = TransactionBuffer::MaxReceiveBytes; - pdc_rx_init(spi_pdc, &pdc_spi_packet, NULL); -} - -#endif - -#if USE_DMAC - -// Our choice of DMA channels to use -const uint32_t CONF_SPI_DMAC_TX_CH = 1; -const uint32_t CONF_SPI_DMAC_RX_CH = 2; - -// Hardware IDs of the SPI transmit and receive DMA interfaces. See atsam datasheet. -const uint32_t DMA_HW_ID_SPI_TX = 1; -const uint32_t DMA_HW_ID_SPI_RX = 2; - -static inline void spi_rx_dma_enable() -{ - dmac_channel_enable(DMAC, CONF_SPI_DMAC_RX_CH); -} - -static inline void spi_tx_dma_enable() -{ - dmac_channel_enable(DMAC, CONF_SPI_DMAC_TX_CH); -} - -static inline void spi_rx_dma_disable() -{ - dmac_channel_disable(DMAC, CONF_SPI_DMAC_RX_CH); -} - -static inline void spi_tx_dma_disable() -{ - dmac_channel_disable(DMAC, CONF_SPI_DMAC_TX_CH); -} - -static bool spi_dma_check_rx_complete() -{ - uint32_t status = DMAC->DMAC_CHSR; - if ( ((status & (DMAC_CHSR_ENA0 << CONF_SPI_DMAC_RX_CH)) == 0) // controller is not enabled, perhaps because it finished a full buffer transfer - || ((status & (DMAC_CHSR_EMPT0 << CONF_SPI_DMAC_RX_CH)) != 0) // controller is enabled, probably suspended, and the FIFO is empty - ) - { - // Disable the channel. - // We also need to set the resume bit, otherwise it remains suspended when we re-enable it. - DMAC->DMAC_CHDR = (DMAC_CHDR_DIS0 << CONF_SPI_DMAC_RX_CH) | (DMAC_CHDR_RES0 << CONF_SPI_DMAC_RX_CH); - return true; - } - return false; -} - -static void spi_tx_dma_setup(const TransactionBuffer *buf, uint32_t maxTransmitLength) -{ - DMAC->DMAC_EBCISR; // clear any pending interrupts - - dmac_channel_set_source_addr(DMAC, CONF_SPI_DMAC_TX_CH, reinterpret_cast<uint32_t>(buf)); - dmac_channel_set_destination_addr(DMAC, CONF_SPI_DMAC_TX_CH, reinterpret_cast<uint32_t>(& SPI->SPI_TDR)); - dmac_channel_set_descriptor_addr(DMAC, CONF_SPI_DMAC_TX_CH, 0); - dmac_channel_set_ctrlA(DMAC, CONF_SPI_DMAC_TX_CH, maxTransmitLength | DMAC_CTRLA_SRC_WIDTH_WORD | DMAC_CTRLA_DST_WIDTH_BYTE); - dmac_channel_set_ctrlB(DMAC, CONF_SPI_DMAC_TX_CH, - DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_DST_INCR_FIXED); -} - -static void spi_rx_dma_setup(const TransactionBuffer *buf) -{ - DMAC->DMAC_EBCISR; // clear any pending interrupts - - dmac_channel_set_source_addr(DMAC, CONF_SPI_DMAC_RX_CH, reinterpret_cast<uint32_t>(& SPI->SPI_RDR)); - dmac_channel_set_destination_addr(DMAC, CONF_SPI_DMAC_RX_CH, reinterpret_cast<uint32_t>(buf)); - dmac_channel_set_descriptor_addr(DMAC, CONF_SPI_DMAC_RX_CH, 0); -// dmac_channel_set_ctrlA(DMAC, CONF_SPI_DMAC_RX_CH, TransactionBuffer::MaxTransferBytes | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_WORD); - dmac_channel_set_ctrlB(DMAC, CONF_SPI_DMAC_RX_CH, - DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_PER2MEM_DMA_FC | DMAC_CTRLB_SRC_INCR_FIXED | DMAC_CTRLB_DST_INCR_INCREMENTING); -} - -#endif - -#if USE_PDC || USE_DMAC - -static void spi_dma_disable() -{ - spi_tx_dma_disable(); - spi_rx_dma_disable(); -} - -#if 0 -/** - * \brief Set SPI slave transfer. - */ -static void spi_slave_dma_setup(bool dataToSend, bool allowReceive) -{ -#if USE_PDC - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS); - - TransactionBuffer *outBufPointer = (dataToSend) ? &outBuffer : reinterpret_cast<TransactionBuffer*>(&dummyOutBuffer); - spi_tx_dma_setup(outBufPointer); - if (allowReceive) - { - outBufPointer->SetDataTaken(); - spi_rx_dma_setup(&inBuffer); - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN); - } - else - { - outBufPointer->ClearDataTaken(); - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN); - } -#endif - -#if USE_DMAC - spi_dma_disable(); - - TransactionBuffer *outBufPointer = (dataToSend) ? &outBuffer : reinterpret_cast<TransactionBuffer*>(&dummyOutBuffer); - if (allowReceive) - { - spi_rx_dma_setup(&inBuffer); - spi_rx_dma_enable(); -// outBufPointer->SetDataTaken(); - } - else - { -// outBufPointer->ClearDataTaken(); - } - -// spi_tx_dma_setup(outBufPointer, (dataToSend) ? TransactionBuffer::MaxTransferBytes : 4 * TransactionBuffer::headerDwords); - spi_tx_dma_enable(); -#endif -} -#endif - -#endif - -namespace WizSpi -{ - // Initialise the SPI interface - void Init() - { - #if USE_PDC - spi_pdc = spi_get_pdc_base(SPI); - // The PDCs are masters 2 and 3 and the SRAM is slave 0. Give the PDCs the highest priority. - matrix_set_master_burst_type(0, MATRIX_ULBT_8_BEAT_BURST); - matrix_set_slave_default_master_type(0, MATRIX_DEFMSTR_LAST_DEFAULT_MASTER); - matrix_set_slave_priority(0, (3 << MATRIX_PRAS0_M2PR_Pos) | (3 << MATRIX_PRAS0_M3PR_Pos)); - matrix_set_slave_slot_cycle(0, 8); - #endif - - #if USE_DMAC - pmc_enable_periph_clk(ID_DMAC); - dmac_init(DMAC); - dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN); - dmac_enable(DMAC); - // The DMAC is master 4 and the SRAM is slave 0. Give the DMAC the highest priority. - matrix_set_slave_default_master_type(0, MATRIX_DEFMSTR_LAST_DEFAULT_MASTER); - matrix_set_slave_priority(0, (3 << MATRIX_PRAS0_M4PR_Pos)); - // Set the slave slot cycle limit. - // If we leave it at the default value of 511 clock cycles, we get transmit underruns due to the HSMCI using the bus for too long. - // A value of 8 seems to work. I haven't tried other values yet. - matrix_set_slave_slot_cycle(0, 8); - #endif - - // Set up the SPI pins - ConfigurePin(g_APinDescription[APIN_SPI_SCK]); - ConfigurePin(g_APinDescription[APIN_SPI_MOSI]); - ConfigurePin(g_APinDescription[APIN_SPI_MISO]); -#if 1 - pinMode(APIN_SPI_SS0, OUTPUT_HIGH); // use manual SS control for now -#else - ConfigurePin(g_APinDescription[APIN_SPI_SS0]); -#endif - - pmc_enable_periph_clk(ID_SPI); - -#if USE_PDC || USE_DMAC - spi_dma_disable(); -#endif - - spi_reset(SPI); // this clears the transmit and receive registers and puts the SPI into slave mode - SPI->SPI_MR = SPI_MR_MSTR // master mode - | SPI_MR_MODFDIS // disable fault detection - | SPI_MR_PCS(SpiPeripheralChannelId); // fixed peripheral select - - // Set SPI mode, clock frequency, CS active after transfer, delay between transfers - const uint16_t baud_div = (uint16_t)spi_calc_baudrate_div(SpiClockFrequency, SystemCoreClock); - const uint32_t csr = SPI_CSR_SCBR(baud_div) // Baud rate - | SPI_CSR_BITS_8_BIT // Transfer bit width - | SPI_CSR_DLYBCT(0) // Transfer delay - | SPI_CSR_CSAAT // Keep CS low after transfer in case we are slow in writing the next byte - | SPI_CSR_NCPHA; // Data is captured on the leading edge of the clock (SPI mode 0) - SPI->SPI_CSR[SpiPeripheralChannelId] = csr; - spi_enable(SPI); - -#if USE_DMAC - // Configure DMA RX channel - dmac_channel_set_configuration(DMAC, CONF_SPI_DMAC_RX_CH, - DMAC_CFG_SRC_PER(DMA_HW_ID_SPI_RX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG); - - // Configure DMA TX channel - dmac_channel_set_configuration(DMAC, CONF_SPI_DMAC_TX_CH, - DMAC_CFG_DST_PER(DMA_HW_ID_SPI_TX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG); -#endif - } - - void Stop() - { - NVIC_DisableIRQ(SPI_IRQn); - spi_disable(SPI); -#if USE_PDC || USE_DMA - spi_dma_check_rx_complete(); - spi_dma_disable(); -#endif - } - - // Wait for transmitter ready returning true if timed out - static inline bool waitForTxReady() - { - uint32_t timeout = SPI_TIMEOUT; - while (!spi_is_tx_ready(SPI)) - { - if (--timeout == 0) - { - return true; - } - } - return false; - } - - // Wait for transmitter empty returning true if timed out - static inline bool waitForTxEmpty() - { - uint32_t timeout = SPI_TIMEOUT; - while (!spi_is_tx_empty(SPI)) - { - if (!timeout--) - { - return true; - } - } - return false; - } - - // Wait for receive data available returning true if timed out - static inline bool waitForRxReady() - { - uint32_t timeout = SPI_TIMEOUT; - while (!spi_is_rx_ready(SPI)) - { - if (--timeout == 0) - { - return true; - } - } - return false; - } - - // Set the SS pin low to address the W5500 - void AssertSS() - { - spi_set_peripheral_chip_select_value(SPI, spi_get_pcs(SpiPeripheralChannelId)); - digitalWrite(SamCsPin, LOW); - } - - // Set the SS pin high again - void ReleaseSS() - { - waitForTxEmpty(); - digitalWrite(SamCsPin, HIGH); - } - - //TODO return type, error returns - uint8_t ExchangeByte(uint8_t b, bool isLast) - { - if (waitForTxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - // Write to transmit register - uint32_t dOut = b; - if (isLast) - { - dOut |= SPI_TDR_LASTXFER; - } - SPI->SPI_TDR = dOut; - - // Wait for receive register - if (waitForRxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - // Get data from receive register - return (uint8_t)SPI->SPI_RDR; - } - - spi_status_t ReadBurst(uint8_t* rx_data, size_t len) - { - for (size_t i = 0; i < len; ++i) - { - uint32_t dOut = 0x000000FF; - if (waitForTxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - // Write to transmit register - if (i + 1 == len) - { - dOut |= SPI_TDR_LASTXFER; - } - SPI->SPI_TDR = dOut; - - // Wait for receive register - if (waitForRxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - // Get data from receive register - *rx_data++ = (uint8_t)SPI->SPI_RDR; - } - - return SPI_OK; - } - - spi_status_t SendBurst(const uint8_t* tx_data, size_t len) - { - for (uint32_t i = 0; i < len; ++i) - { - uint32_t dOut = (uint32_t)*tx_data++; - if (waitForTxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - // Write to transmit register - if (i + 1 == len) - { - dOut |= SPI_TDR_LASTXFER; - } - SPI->SPI_TDR = dOut; - // Wait for receive register - if (waitForRxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - // Get data from receive register - (void)SPI->SPI_RDR; - } - - return SPI_OK; - } - -} // end namespace - -// End diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/WizSpi.h b/src/DuetNG/DuetEthernet/Ethernet3/utility/WizSpi.h deleted file mode 100644 index 214c668f..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/WizSpi.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Spi.h - * - * Created on: 16 Dec 2016 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_ETHERNET3_UTILITY_WIZSPI_H_ -#define SRC_DUETNG_DUETETHERNET_ETHERNET3_UTILITY_WIZSPI_H_ - -#include "spi.h" - -namespace WizSpi -{ - void Init(); - void Stop(); - void AssertSS(); - void ReleaseSS(); - uint8_t ExchangeByte(uint8_t b, bool isLast); - spi_status_t ReadBurst(uint8_t* rx_data, size_t len); - spi_status_t SendBurst(const uint8_t* tx_data, size_t len); -} - -#endif /* SRC_DUETNG_DUETETHERNET_ETHERNET3_UTILITY_WIZSPI_H_ */ diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/socket.cpp b/src/DuetNG/DuetEthernet/Ethernet3/utility/socket.cpp deleted file mode 100644 index 75f7a993..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/socket.cpp +++ /dev/null @@ -1,413 +0,0 @@ - /* - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - */ - -#include "utility/w5500.h" -#include "utility/socket.h" - -static uint16_t local_port; - -/** - * @brief This Socket function initialize the channel in perticular mode, and set the port and wait for w5500 done it. - * @return 1 for success else 0. - */ -uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) -{ - if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE)) - { - close(s); - w5500.writeSnMR(s, protocol | flag); - if (port != 0) { - w5500.writeSnPORT(s, port); - } - else { - local_port++; // if don't set the source port, set local_port number. - w5500.writeSnPORT(s, local_port); - } - - w5500.execCmdSn(s, Sock_OPEN); - - return 1; - } - - return 0; -} - - -/** - * @brief This function close the socket and parameter is "s" which represent the socket number - */ -void close(SOCKET s) -{ - w5500.execCmdSn(s, Sock_CLOSE); - w5500.writeSnIR(s, 0xFF); -} - - -/** - * @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer. - * @return 1 for success else 0. - */ -uint8_t listen(SOCKET s) -{ - if (w5500.readSnSR(s) != SnSR::INIT) - return 0; - w5500.execCmdSn(s, Sock_LISTEN); - return 1; -} - - -/** - * @brief This function established the connection for the channel in Active (client) mode. - * This function waits for the untill the connection is established. - * - * @return 1 for success else 0. - */ -uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port) -{ - if - ( - ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) || - ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || - (port == 0x00) - ) - return 0; - - // set destination IP - w5500.writeSnDIPR(s, addr); - w5500.writeSnDPORT(s, port); - w5500.execCmdSn(s, Sock_CONNECT); - - return 1; -} - - - -/** - * @brief This function used for disconnect the socket and parameter is "s" which represent the socket number - * @return 1 for success else 0. - */ -void disconnect(SOCKET s) -{ - w5500.execCmdSn(s, Sock_DISCON); -} - - -/** - * @brief This function used to send the data in TCP mode - * @return 1 for success else 0. - */ -uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) -{ - uint8_t status=0; - uint16_t ret=0; - uint16_t freesize=0; - - if (len > w5500.SSIZE) - ret = w5500.SSIZE; // check size not to exceed MAX size. - else - ret = len; - - // if freebuf is available, start. - do - { - freesize = w5500.getTXFreeSize(s); - status = w5500.readSnSR(s); - if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) - { - ret = 0; - break; - } - } - while (freesize < ret); - - // copy data - w5500.send_data_processing(s, (uint8_t *)buf, ret); - w5500.execCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while ( (w5500.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) - { - /* m2008.01 [bj] : reduce code */ - if ( w5500.readSnSR(s) == SnSR::CLOSED ) - { - close(s); - return 0; - } - } - /* +2008.01 bj */ - w5500.writeSnIR(s, SnIR::SEND_OK); - return ret; -} - - -/** - * @brief This function is an application I/F function which is used to receive the data in TCP mode. - * It continues to wait for data as much as the application wants to receive. - * - * @return received data size for success else -1. - */ -int16_t recv(SOCKET s, uint8_t *buf, int16_t len) -{ - // Check how much data is available - int16_t ret = w5500.getRXReceivedSize(s); - if ( ret == 0 ) - { - // No data available. - uint8_t status = w5500.readSnSR(s); - if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT ) - { - // The remote end has closed its side of the connection, so this is the eof state - ret = 0; - } - else - { - // The connection is still up, but there's no data waiting to be read - ret = -1; - } - } - else if (ret > len) - { - ret = len; - } - - if ( ret > 0 ) - { - w5500.recv_data_processing(s, buf, ret); - w5500.execCmdSn(s, Sock_RECV); - } - return ret; -} - - -/** - * @brief Returns the first byte in the receive queue (no checking) - * - * @return - */ -uint16_t peek(SOCKET s, uint8_t *buf) -{ - w5500.recv_data_processing(s, buf, 1, 1); - - return 1; -} - - -/** - * @brief This function is an application I/F function which is used to send the data for other then TCP mode. - * Unlike TCP transmission, The peer's destination address and the port is needed. - * - * @return This function return send data size for success else -1. - */ -uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port) -{ - uint16_t ret=0; - - if (len > w5500.SSIZE) ret = w5500.SSIZE; // check size not to exceed MAX size. - else ret = len; - - if - ( - ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || - ((port == 0x00)) ||(ret == 0) - ) - { - /* +2008.01 [bj] : added return value */ - ret = 0; - } - else - { - w5500.writeSnDIPR(s, addr); - w5500.writeSnDPORT(s, port); - - // copy data - w5500.send_data_processing(s, (uint8_t *)buf, ret); - w5500.execCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while ( (w5500.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) - { - if (w5500.readSnIR(s) & SnIR::TIMEOUT) - { - /* +2008.01 [bj]: clear interrupt */ - w5500.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */ - return 0; - } - } - - /* +2008.01 bj */ - w5500.writeSnIR(s, SnIR::SEND_OK); - } - return ret; -} - - -/** - * @brief This function is an application I/F function which is used to receive the data in other then - * TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well. - * - * @return This function return received data size for success else -1. - */ -uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port) -{ - uint8_t head[8]; - uint16_t data_len=0; - uint16_t ptr=0; - - if ( len > 0 ) - { - ptr = w5500.readSnRX_RD(s); - switch (w5500.readSnMR(s) & 0x07) - { - case SnMR::UDP : - w5500.read_data(s, ptr, head, 0x08); - ptr += 8; - // read peer's IP address, port number. - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - *port = head[4]; - *port = (*port << 8) + head[5]; - data_len = head[6]; - data_len = (data_len << 8) + head[7]; - - w5500.read_data(s, ptr, buf, data_len); // data copy. - ptr += data_len; - - w5500.writeSnRX_RD(s, ptr); - break; - - case SnMR::IPRAW : - w5500.read_data(s, ptr, head, 0x06); - ptr += 6; - - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - data_len = head[4]; - data_len = (data_len << 8) + head[5]; - - w5500.read_data(s, ptr, buf, data_len); // data copy. - ptr += data_len; - - w5500.writeSnRX_RD(s, ptr); - break; - - case SnMR::MACRAW: - w5500.read_data(s, ptr, head, 2); - ptr+=2; - data_len = head[0]; - data_len = (data_len<<8) + head[1] - 2; - - w5500.read_data(s, ptr, buf, data_len); - ptr += data_len; - w5500.writeSnRX_RD(s, ptr); - break; - - default : - break; - } - w5500.execCmdSn(s, Sock_RECV); - } - return data_len; -} - -/** - * @brief Wait for buffered transmission to complete. - */ -void flush(SOCKET s) { - // TODO -} - -uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) -{ - //uint8_t status=0; - uint16_t ret=0; - - if (len > w5500.SSIZE) - ret = w5500.SSIZE; // check size not to exceed MAX size. - else - ret = len; - - if (ret == 0) - return 0; - - w5500.send_data_processing(s, (uint8_t *)buf, ret); - w5500.execCmdSn(s, Sock_SEND); - - while ( (w5500.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) - { - //status = w5500.readSnSR(s); - (void)w5500.readSnSR(s); - if (w5500.readSnIR(s) & SnIR::TIMEOUT) - { - /* in case of igmp, if send fails, then socket closed */ - /* if you want change, remove this code. */ - close(s); - return 0; - } - } - - w5500.writeSnIR(s, SnIR::SEND_OK); - return ret; -} - -uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) -{ - uint16_t ret =0; - if (len > w5500.getTXFreeSize(s)) - { - ret = w5500.getTXFreeSize(s); // check size not to exceed MAX size. - } - else - { - ret = len; - } - w5500.send_data_processing_offset(s, offset, buf, ret); - return ret; -} - -int startUDP(SOCKET s, uint8_t* addr, uint16_t port) -{ - if - ( - ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || - ((port == 0x00)) - ) - { - return 0; - } - else - { - w5500.writeSnDIPR(s, addr); - w5500.writeSnDPORT(s, port); - return 1; - } -} - -int sendUDP(SOCKET s) -{ - w5500.execCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while ( (w5500.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) - { - if (w5500.readSnIR(s) & SnIR::TIMEOUT) - { - /* +2008.01 [bj]: clear interrupt */ - w5500.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT)); - return 0; - } - } - - /* +2008.01 bj */ - w5500.writeSnIR(s, SnIR::SEND_OK); - - /* Sent ok */ - return 1; -} - diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/socket.h b/src/DuetNG/DuetEthernet/Ethernet3/utility/socket.h deleted file mode 100644 index 903280c0..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/socket.h +++ /dev/null @@ -1,48 +0,0 @@ - /* - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - */ - -#ifndef _SOCKET_H_ -#define _SOCKET_H_ - -#include "utility/w5500.h" - -extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode) -extern void close(SOCKET s); // Close socket -extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection) -extern void disconnect(SOCKET s); // disconnect the connection -extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection) -extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP) -extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP) -extern uint16_t peek(SOCKET s, uint8_t *buf); -extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW) -extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW) -extern void flush(SOCKET s); // Wait for transmission to complete - -extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len); - -// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a -// number of calls before being sent -/* - @brief This function sets up a UDP datagram, the data for which will be provided by one - or more calls to bufferData and then finally sent with sendUDP. - @return 1 if the datagram was successfully set up, or 0 if there was an error -*/ -extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port); -/* - @brief This function copies up to len bytes of data from buf into a UDP datagram to be - sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. - @return Number of bytes successfully buffered -*/ -uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len); -/* - @brief Send a UDP datagram built up from a sequence of startUDP followed by one or more - calls to bufferData. - @return 1 if the datagram was successfully sent, or 0 if there was an error -*/ -int sendUDP(SOCKET s); - -#endif -/* _SOCKET_H_ */ diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/util.h b/src/DuetNG/DuetEthernet/Ethernet3/utility/util.h deleted file mode 100644 index 8a254408..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/util.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef UTIL_H -#define UTIL_H - -static inline uint16_t htons(uint16_t x) -{ - return (x << 8) | ((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) - -// Get a 16 bit word in network byte order from a buffer -static inline uint16_t get16nb(const uint8_t *buf) -{ - return ((uint16_t)buf[0] << 8) | buf[1]; -} - -// Get a 32 bit word in network byte order from a buffer -static inline uint16_t get32nb(const uint8_t *buf) -{ - return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | buf[3]; -} - -// Get a 16 bit word in native byte order from a buffer -static inline uint16_t get16(const uint8_t *buf) -{ - return ((uint16_t)buf[1] << 8) | buf[0]; -} - -// Put a 16-bit word in native byte order in a buffer -static inline void put16(uint8_t *buf, uint16_t n) -{ - buf[0] = (uint8_t)n; - buf[1] = (uint8_t)(n >> 8); -} - -#endif diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/w5500.cpp b/src/DuetNG/DuetEthernet/Ethernet3/utility/w5500.cpp deleted file mode 100644 index 553f9ee5..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/w5500.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2010 by WIZnet <support@wiznet.co.kr> - * - * 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. - * - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - */ - -#include <stdio.h> -#include <string.h> -#include "Core.h" - -#include "utility/w5500.h" -#include "utility/WizSpi.h" - -// W5500 controller instance -W5500Class w5500; - - -void W5500Class::init(void) -{ - WizSpi::Init(); - - for (int i=0; i<MAX_SOCK_NUM; i++) - { - const uint8_t cntl_byte = (0x0C + (i<<5)); - write( 0x1E, cntl_byte, 2); //0x1E - Sn_RXBUF_SIZE - write( 0x1F, cntl_byte, 2); //0x1F - Sn_TXBUF_SIZE - } -} - -void W5500Class::stop() -{ - WizSpi::Stop(); -} - -uint16_t W5500Class::getTXFreeSize(SOCKET s) -{ - uint16_t val=0, val1=0; - do { - val1 = readSnTX_FSR(s); - if (val1 != 0) - val = readSnTX_FSR(s); - } - while (val != val1); - return val; -} - -uint16_t W5500Class::getRXReceivedSize(SOCKET s) -{ - uint16_t val=0,val1=0; - do { - val1 = readSnRX_RSR(s); - if (val1 != 0) - val = readSnRX_RSR(s); - } - while (val != val1); - return val; -} - -void W5500Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len) -{ - // This is same as having no offset in a call to send_data_processing_offset - send_data_processing_offset(s, 0, data, len); -} - -void W5500Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len) -{ - uint16_t ptr = readSnTX_WR(s); - uint8_t cntl_byte = (0x14+(s<<5)); - ptr += data_offset; - write(ptr, cntl_byte, data, len); - ptr += len; - writeSnTX_WR(s, ptr); - -} - -void W5500Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) -{ - uint16_t ptr = readSnRX_RD(s); - - read_data(s, ptr, data, len); - if (!peek) - { - ptr += len; - writeSnRX_RD(s, ptr); - } -} - -void W5500Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len) -{ - uint8_t cntl_byte = (0x18+(s<<5)); - read((uint16_t)src , cntl_byte, (uint8_t *)dst, len); -} - -uint8_t W5500Class::write(uint16_t _addr, uint8_t _cb, uint8_t _data) -{ - WizSpi::AssertSS(); - WizSpi::ExchangeByte(_addr >> 8, false); - WizSpi::ExchangeByte(_addr & 0xFF, false); - WizSpi::ExchangeByte(_cb, false); - WizSpi::ExchangeByte(_data, true); - WizSpi::ReleaseSS(); - return 1; -} - -uint16_t W5500Class::write(uint16_t _addr, uint8_t _cb, const uint8_t *_buf, uint16_t _len) -{ - WizSpi::AssertSS(); - WizSpi::ExchangeByte(_addr >> 8, false); - WizSpi::ExchangeByte(_addr & 0xFF, false); - WizSpi::ExchangeByte(_cb, false); - WizSpi::SendBurst(_buf, _len); - WizSpi::ReleaseSS(); - return _len; -} - -uint8_t W5500Class::read(uint16_t _addr, uint8_t _cb) -{ - WizSpi::AssertSS(); - WizSpi::ExchangeByte(_addr >> 8, false); - WizSpi::ExchangeByte(_addr & 0xFF, false); - WizSpi::ExchangeByte(_cb, false); - const uint8_t _data = WizSpi::ExchangeByte(0, true); - WizSpi::ReleaseSS(); - return _data; -} - -uint16_t W5500Class::read(uint16_t _addr, uint8_t _cb, uint8_t *_buf, uint16_t _len) -{ - WizSpi::AssertSS(); - WizSpi::ExchangeByte(_addr >> 8, false); - WizSpi::ExchangeByte(_addr & 0xFF, false); - WizSpi::ExchangeByte(_cb, false); - WizSpi::ReadBurst(_buf, _len); - WizSpi::ReleaseSS(); - return _len; -} - -void W5500Class::execCmdSn(SOCKET s, SockCMD _cmd) { - // Send command to socket - writeSnCR(s, _cmd); - // Wait for command to complete - while (readSnCR(s)) - ; -} - -// End diff --git a/src/DuetNG/DuetEthernet/Ethernet3/utility/w5500.h b/src/DuetNG/DuetEthernet/Ethernet3/utility/w5500.h deleted file mode 100644 index 418da9a8..00000000 --- a/src/DuetNG/DuetEthernet/Ethernet3/utility/w5500.h +++ /dev/null @@ -1,443 +0,0 @@ -/* -* Copyright (c) 2010 by WIZnet <support@wiznet.co.kr> - * - * 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. - * - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - */ - -#ifndef W5500_H_INCLUDED -#define W5500_H_INCLUDED - -#include <cstdint> - -// The SAM4E header files define UDP as a macro for accessing the USB Device Port, which clashes with UDP in this module. So un-define it. -#undef UDP - -#define MAX_SOCK_NUM 8 - -typedef uint8_t SOCKET; -/* -class MR { -public: - static const uint8_t RST = 0x80; - static const uint8_t PB = 0x10; - static const uint8_t PPPOE = 0x08; - static const uint8_t LB = 0x04; - static const uint8_t AI = 0x02; - static const uint8_t IND = 0x01; -}; -*/ -/* -class IR { -public: - static const uint8_t CONFLICT = 0x80; - static const uint8_t UNREACH = 0x40; - static const uint8_t PPPoE = 0x20; - static const uint8_t SOCK0 = 0x01; - static const uint8_t SOCK1 = 0x02; - static const uint8_t SOCK2 = 0x04; - static const uint8_t SOCK3 = 0x08; - static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; -}; -*/ - -class SnMR { -public: - static const uint8_t CLOSE = 0x00; - static const uint8_t TCP = 0x01; - static const uint8_t UDP = 0x02; - static const uint8_t IPRAW = 0x03; - static const uint8_t MACRAW = 0x04; - static const uint8_t PPPOE = 0x05; - static const uint8_t ND = 0x20; - static const uint8_t MULTI = 0x80; -}; - -enum SockCMD { - Sock_OPEN = 0x01, - Sock_LISTEN = 0x02, - Sock_CONNECT = 0x04, - Sock_DISCON = 0x08, - Sock_CLOSE = 0x10, - Sock_SEND = 0x20, - Sock_SEND_MAC = 0x21, - Sock_SEND_KEEP = 0x22, - Sock_RECV = 0x40 -}; - -/*class SnCmd { -public: - static const uint8_t OPEN = 0x01; - static const uint8_t LISTEN = 0x02; - static const uint8_t CONNECT = 0x04; - static const uint8_t DISCON = 0x08; - static const uint8_t CLOSE = 0x10; - static const uint8_t SEND = 0x20; - static const uint8_t SEND_MAC = 0x21; - static const uint8_t SEND_KEEP = 0x22; - static const uint8_t RECV = 0x40; -}; -*/ - -class SnIR { -public: - static const uint8_t SEND_OK = 0x10; - static const uint8_t TIMEOUT = 0x08; - static const uint8_t RECV = 0x04; - static const uint8_t DISCON = 0x02; - static const uint8_t CON = 0x01; -}; - -class SnSR { -public: - static const uint8_t CLOSED = 0x00; - static const uint8_t INIT = 0x13; - static const uint8_t LISTEN = 0x14; - static const uint8_t SYNSENT = 0x15; - static const uint8_t SYNRECV = 0x16; - static const uint8_t ESTABLISHED = 0x17; - static const uint8_t FIN_WAIT = 0x18; - static const uint8_t CLOSING = 0x1A; - static const uint8_t TIME_WAIT = 0x1B; - static const uint8_t CLOSE_WAIT = 0x1C; - static const uint8_t LAST_ACK = 0x1D; - static const uint8_t UDP = 0x22; - static const uint8_t IPRAW = 0x32; - static const uint8_t MACRAW = 0x42; - static const uint8_t PPPOE = 0x5F; -}; - -class IPPROTO { -public: - static const uint8_t IP = 0; - static const uint8_t ICMP = 1; - static const uint8_t IGMP = 2; - static const uint8_t GGP = 3; - static const uint8_t TCP = 6; - static const uint8_t PUP = 12; - static const uint8_t UDP = 17; - static const uint8_t IDP = 22; - static const uint8_t ND = 77; - static const uint8_t RAW = 255; -}; - -class W5500Class { - -public: - void init(); - - void stop(); - - /** - * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. - * - * It calculate the actual physical address where one has to read - * the data from Receive buffer. Here also take care of the condition while it exceed - * the Rx memory uper-bound of socket. - */ - void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); - - /** - * @brief This function is being called by send() and sendto() function also. - * - * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer - * register. User should read upper byte first and lower byte later to get proper value. - */ - void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); - /** - * @brief A copy of send_data_processing that uses the provided ptr for the - * write offset. Only needed for the "streaming" UDP API, where - * a single UDP packet is built up over a number of calls to - * send_data_processing_ptr, because TX_WR doesn't seem to get updated - * correctly in those scenarios - * @param ptr value to use in place of TX_WR. If 0, then the value is read - * in from TX_WR - * @return New value for ptr, to be used in the next call - */ - // FIXME Update documentation - void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); - - /** - * @brief This function is being called by recv() also. - * - * This function read the Rx read pointer register - * and after copy the data from receive buffer update the Rx write pointer register. - * User should read upper byte first and lower byte later to get proper value. - */ - void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); - - inline void setGatewayIp(const uint8_t *_addr); - inline void getGatewayIp(uint8_t *_addr); - - inline void setSubnetMask(const uint8_t *_addr); - inline void getSubnetMask(uint8_t *_addr); - - inline void setMACAddress(const uint8_t * addr); - inline void getMACAddress(uint8_t * addr); - - inline void setIPAddress(const uint8_t * addr); - inline void getIPAddress(uint8_t * addr); - - inline void setRetransmissionTime(uint16_t timeout); - inline void setRetransmissionCount(uint8_t _retry); - - inline void setPHYCFGR(uint8_t _val); - inline uint8_t getPHYCFGR(); - - void execCmdSn(SOCKET s, SockCMD _cmd); - - uint16_t getTXFreeSize(SOCKET s); - uint16_t getRXReceivedSize(SOCKET s); - - - // W5500 Registers - // --------------- -private: - static uint8_t write(uint16_t _addr, uint8_t _cb, uint8_t _data); - static uint16_t write(uint16_t _addr, uint8_t _cb, const uint8_t *buf, uint16_t len); - static uint8_t read(uint16_t _addr, uint8_t _cb ); - static uint16_t read(uint16_t _addr, uint8_t _cb, uint8_t *buf, uint16_t len); - -#define __GP_REGISTER8(name, address) \ - static inline void write##name(uint8_t _data) { \ - write(address, 0x04, _data); \ - } \ - static inline uint8_t read##name() { \ - return read(address, 0x00); \ - } -#define __GP_REGISTER16(name, address) \ - static void write##name(uint16_t _data) { \ - write(address, 0x04, _data >> 8); \ - write(address+1, 0x04, _data & 0xFF); \ - } \ - static uint16_t read##name() { \ - uint16_t res = read(address, 0x00); \ - res = (res << 8) + read(address + 1, 0x00); \ - return res; \ - } -#define __GP_REGISTER_N(name, address, size) \ - static uint16_t write##name(const uint8_t *_buff) { \ - return write(address, 0x04, _buff, size); \ - } \ - static uint16_t read##name(uint8_t *_buff) { \ - return read(address, 0x00, _buff, size); \ - } - -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, 0x0019); // Timeout address - __GP_REGISTER8 (RCR, 0x001B); // Retry count - __GP_REGISTER_N(UIPR, 0x0028, 4); // Unreachable IP address in UDP mode - __GP_REGISTER16(UPORT, 0x002C); // Unreachable Port address in UDP mode - __GP_REGISTER8 (PHYCFGR, 0x002E); // PHY Configuration register, default value: 0b 1011 1xxx - __GP_REGISTER8 (VERSIONR, 0x0039); // Version register, should return 0x04 - - -#undef __GP_REGISTER8 -#undef __GP_REGISTER16 -#undef __GP_REGISTER_N - - // W5500 Socket registers - // ---------------------- -private: - static inline uint8_t readSn(SOCKET _s, uint16_t _addr); - static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); - static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); - static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); - - //static const uint16_t CH_BASE = 0x0000; - //static const uint16_t CH_SIZE = 0x0000; - -#define __SOCKET_REGISTER8(name, address) \ - static inline void write##name(SOCKET _s, uint8_t _data) { \ - writeSn(_s, address, _data); \ - } \ - static inline uint8_t read##name(SOCKET _s) { \ - return readSn(_s, address); \ - } -#if defined(REL_GR_KURUMI) || defined(REL_GR_KURUMI_PROTOTYPE) -#define __SOCKET_REGISTER16(name, address) \ - static void write##name(SOCKET _s, uint16_t _data) { \ - writeSn(_s, address, _data >> 8); \ - writeSn(_s, address+1, _data & 0xFF); \ - } \ - static uint16_t read##name(SOCKET _s) { \ - uint16_t res = readSn(_s, address); \ - uint16_t res2 = readSn(_s,address + 1); \ - res = res << 8; \ - res2 = res2 & 0xFF; \ - res = res | res2; \ - return res; \ - } -#else -#define __SOCKET_REGISTER16(name, address) \ - static void write##name(SOCKET _s, uint16_t _data) { \ - writeSn(_s, address, _data >> 8); \ - writeSn(_s, address+1, _data & 0xFF); \ - } \ - static uint16_t read##name(SOCKET _s) { \ - uint16_t res = readSn(_s, address); \ - res = (res << 8) + readSn(_s, address + 1); \ - return res; \ - } -#endif -#define __SOCKET_REGISTER_N(name, address, size) \ - static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ - return writeSn(_s, address, _buff, size); \ - } \ - static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ - return readSn(_s, address, _buff, size); \ - } - -public: - __SOCKET_REGISTER8(SnMR, 0x0000) // Mode - __SOCKET_REGISTER8(SnCR, 0x0001) // Command - __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt - __SOCKET_REGISTER8(SnSR, 0x0003) // Status - __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port - __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr - __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr - __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port - __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size - __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode - __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS - __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL - __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size - __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer - __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer - __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?) - -#undef __SOCKET_REGISTER8 -#undef __SOCKET_REGISTER16 -#undef __SOCKET_REGISTER_N - - -private: - static const uint8_t RST = 7; // Reset BIT - static const int SOCKETS = 8; - -public: - static const uint16_t SSIZE = 2048; // Max Tx buffer size -private: - static const uint16_t RSIZE = 2048; // Max Rx buffer size - -private: -#if defined(ARDUINO_ARCH_AVR) -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) - inline static void initSS() { DDRB |= _BV(4); }; - inline static void setSS() { PORTB &= ~_BV(4); }; - inline static void resetSS() { PORTB |= _BV(4); }; -#elif defined(__AVR_ATmega32U4__) - inline static void initSS() { DDRB |= _BV(6); }; - inline static void setSS() { PORTB &= ~_BV(6); }; - inline static void resetSS() { PORTB |= _BV(6); }; -#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) - inline static void initSS() { DDRB |= _BV(0); }; - inline static void setSS() { PORTB &= ~_BV(0); }; - inline static void resetSS() { PORTB |= _BV(0); }; -#elif defined(REL_GR_KURUMI) || defined(REL_GR_KURUMI_PROTOTYPE) - inline static void initSS() { pinMode(SS, OUTPUT); - digitalWrite(SS, HIGH); }; - inline static void setSS() { digitalWrite(SS, LOW); }; - inline static void resetSS() { digitalWrite(SS, HIGH); }; -#else - inline static void initSS() { DDRB |= _BV(2); }; - inline static void setSS() { PORTB &= ~_BV(2); }; - inline static void resetSS() { PORTB |= _BV(2); }; -#endif -#elif defined(ARDUINO_ARCH_SAMD) - inline static void initSS() { PORT->Group[g_APinDescription[10].ulPort].PINCFG[g_APinDescription[10].ulPin].reg&=~(uint8_t)(PORT_PINCFG_INEN) ; - PORT->Group[g_APinDescription[10].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[10].ulPin) ; - PORT->Group[g_APinDescription[10].ulPort].PINCFG[g_APinDescription[10].ulPin].reg=(uint8_t)(PORT_PINCFG_PULLEN) ; - PORT->Group[g_APinDescription[10].ulPort].OUTSET.reg = (1ul << g_APinDescription[10].ulPin) ; }; - inline static void setSS() { PORT->Group[g_APinDescription[10].ulPort].OUTCLR.reg = (1ul << g_APinDescription[10].ulPin) ; }; - inline static void resetSS() { PORT->Group[g_APinDescription[10].ulPort].OUTSET.reg = (1ul << g_APinDescription[10].ulPin) ; }; -#endif // ARDUINO_ARCH_AVR -}; - -extern W5500Class w5500; - -uint8_t W5500Class::readSn(SOCKET _s, uint16_t _addr) { - uint8_t cntl_byte = (_s<<5)+0x08; - return read(_addr, cntl_byte); -} - -uint8_t W5500Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { - uint8_t cntl_byte = (_s<<5)+0x0C; - return write(_addr, cntl_byte, _data); -} - -uint16_t W5500Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { - uint8_t cntl_byte = (_s<<5)+0x08; - return read(_addr, cntl_byte, _buf, _len ); -} - -uint16_t W5500Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { - uint8_t cntl_byte = (_s<<5)+0x0C; - return write(_addr, cntl_byte, _buf, _len); -} - -void W5500Class::getGatewayIp(uint8_t *_addr) { - readGAR(_addr); -} - -void W5500Class::setGatewayIp(const uint8_t *_addr) { - writeGAR(_addr); -} - -void W5500Class::getSubnetMask(uint8_t *_addr) { - readSUBR(_addr); -} - -void W5500Class::setSubnetMask(const uint8_t *_addr) { - writeSUBR(_addr); -} - -void W5500Class::getMACAddress(uint8_t *_addr) { - readSHAR(_addr); -} - -void W5500Class::setMACAddress(const uint8_t *_addr) { - writeSHAR(_addr); -} - -void W5500Class::getIPAddress(uint8_t *_addr) { - readSIPR(_addr); -} - -void W5500Class::setIPAddress(const uint8_t *_addr) { - writeSIPR(_addr); -} - -void W5500Class::setRetransmissionTime(uint16_t _timeout) { - writeRTR(_timeout); -} - -void W5500Class::setRetransmissionCount(uint8_t _retry) { - writeRCR(_retry); -} - -void W5500Class::setPHYCFGR(uint8_t _val) { - writePHYCFGR(_val); -} - -uint8_t W5500Class::getPHYCFGR() { -// readPHYCFGR(); - return read(0x002E, 0x00); -} - -#endif diff --git a/src/DuetNG/DuetEthernet/Network.cpp b/src/DuetNG/DuetEthernet/Network.cpp index 4f742cb8..5f7bd72c 100644 --- a/src/DuetNG/DuetEthernet/Network.cpp +++ b/src/DuetNG/DuetEthernet/Network.cpp @@ -20,21 +20,23 @@ void Network::SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[ Network::Network(Platform* p) : platform(p), lastTickMillis(0), - freeTransactions(nullptr), readyTransactions(nullptr), writingTransactions(nullptr), httpPort(DefaultHttpPort), state(NetworkState::disabled), activated(false) { - SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway); - strcpy(hostname, HOSTNAME); } void Network::Init() { - // Ensure that the chip is in the reset state + // Ensure that the W5500 chip is in the reset state pinMode(EspResetPin, OUTPUT_LOW); state = NetworkState::disabled; longWait = platform->Time(); lastTickMillis = millis(); - InitSockets(); + + NetworkBuffer::AllocateBuffers(NetworkBufferCount); + NetworkTransaction::AllocateTransactions(NetworkTransactionCount); + + SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway); + strcpy(hostname, HOSTNAME); } // This is called at the end of config.g processing. @@ -53,7 +55,8 @@ void Network::Exit() Stop(); } -void Network::Spin() +// Main spin loop. If 'full' is true then we are being called from the main spin loop. If false then we are being called during HSMCI idle time. +void Network::Spin(bool full) { switch(state) { @@ -63,9 +66,8 @@ void Network::Spin() break; case NetworkState::establishingLink: - if (wizphy_getphylink() == PHY_LINK_ON) + if (full && wizphy_getphylink() == PHY_LINK_ON) { - usingDhcp = (ipAddress[0] == 0 && ipAddress[1] == 0 && ipAddress[2] == 0 && ipAddress[3] == 0); if (usingDhcp) { @@ -85,38 +87,44 @@ void Network::Spin() break; case NetworkState::obtainingIP: - if (wizphy_getphylink() == PHY_LINK_ON) + if (full) { - const uint32_t now = millis(); - if (now - lastTickMillis >= 1000) + if (wizphy_getphylink() == PHY_LINK_ON) { - lastTickMillis += 1000; - DHCP_time_handler(); + const uint32_t now = millis(); + if (now - lastTickMillis >= 1000) + { + lastTickMillis += 1000; + DHCP_time_handler(); + } + const DhcpRunResult ret = DHCP_run(); + if (ret == DhcpRunResult::DHCP_IP_ASSIGN) + { + debugPrintf("IP address obtained, network running\n"); + getSIPR(ipAddress); + // Send mDNS announcement so that some routers can perform hostname mapping + // if this board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N) + //mdns_announce(); + InitSockets(); + state = NetworkState::active; + } } - const DhcpRunResult ret = DHCP_run(); - if (ret == DhcpRunResult::DHCP_IP_ASSIGN) + else { - debugPrintf("IP address obtained, network running\n"); - getSIPR(ipAddress); - // Send mDNS announcement so that some routers can perform hostname mapping - // if this board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N) - //mdns_announce(); - InitSockets(); - state = NetworkState::active; + debugPrintf("Lost phy link\n"); + DHCP_stop(); + TerminateSockets(); + state = NetworkState::establishingLink; } } - else - { - DHCP_stop(); - TerminateSockets(); - state = NetworkState::establishingLink; - } break; case NetworkState::active: + // Check that the link is still up if (wizphy_getphylink() == PHY_LINK_ON) { - if (usingDhcp) + // Maintain DHCP + if (full && usingDhcp) { const uint32_t now = millis(); if (now - lastTickMillis >= 1000) @@ -127,50 +135,28 @@ void Network::Spin() const DhcpRunResult ret = DHCP_run(); if (ret == DhcpRunResult::DHCP_IP_CHANGED) { + debugPrintf("IP address changed\n"); getSIPR(ipAddress); } } - sockets[nextSocketToPoll].Poll(); + // Poll the next TCP socket + sockets[nextSocketToPoll].Poll(full); + + // Move on to the next TCP socket for next time ++nextSocketToPoll; if (nextSocketToPoll == NumTcpSockets) { nextSocketToPoll = 0; } -#if 0 - // See if we can send anything - NetworkTransaction *transaction = writingTransactions; - if (transaction != nullptr /*&& sendingConnection == nullptr*/ ) - { - if (transaction->GetNext() != nullptr) - { - // Data is supposed to be sent and the last packet has been acknowledged. - // Rotate the transactions so every client is served even while multiple files are sent - NetworkTransaction *next = transaction->GetNext(); - writingTransactions = next; - AppendTransaction(&writingTransactions, transaction); - transaction = next; - } - - if (transaction->Send()) - { - // This transaction can be released, do this here - writingTransactions = transaction->GetNext(); - PrependTransaction(&freeTransactions, transaction); - - // If there is more data to write on this connection, do it sometime soon - NetworkTransaction *nextWrite = transaction->GetNextWrite(); - if (nextWrite != nullptr) - { - PrependTransaction(&writingTransactions, nextWrite); - } - } - } -#endif } - else + else if (full) { - DHCP_stop(); + debugPrintf("Lost phy link\n"); + if (usingDhcp) + { + DHCP_stop(); + } TerminateSockets(); state = NetworkState::establishingLink; } @@ -236,7 +222,7 @@ void Network::Disable() if (activated && state != NetworkState::disabled) { Stop(); - platform->Message(GENERIC_MESSAGE, "WiFi server stopped\n"); + platform->Message(GENERIC_MESSAGE, "Network stopped\n"); } } @@ -289,180 +275,103 @@ void Network::SetHostname(const char *name) bool Network::Lock() { - //TODO return true; } void Network::Unlock() { - //TODO } bool Network::InLwip() const { - //TODO return false; } // This is called by the web server to get the next networking transaction. // -// If cs is NULL, the transaction from the head of readyTransactions will be retrieved. -// If cs is not NULL, the first transaction with the matching connection will be returned. +// If conn is NoConnection, the transaction from the head of readyTransactions will be retrieved. +// If conn is not NoConnection, the first transaction with the matching connection will be returned. // -// This method also ensures that the retrieved transaction is moved to the first item of -// readyTransactions, so that a subsequent call with a NULL cs parameter will return exactly -// the same instance. +// This method also ensures that a subsequent call with a null connection parameter will return exactly the same instance. NetworkTransaction *Network::GetTransaction(Connection conn) { -#if 1 - return nullptr; -#else - // See if there is any transaction at all - NetworkTransaction *transaction = readyTransactions; - if (transaction == nullptr) - { - return nullptr; - } - - // If no specific connection is specified or if the first item already matches the - // connection we are looking for, just return it - if (cs == nullptr || transaction->GetConnection() == cs) - { - return transaction; - } - - // We are looking for a specific transaction, but it's not the first item. - // Search for it and move it to the head of readyTransactions - NetworkTransaction *previous = transaction; - for(NetworkTransaction *item = transaction->next; item != nullptr; item = item->next) + if (state == NetworkState::active) { - if (item->GetConnection() == cs) + if (conn != NoConnection) { - previous->next = item->next; - item->next = readyTransactions; - readyTransactions = item; - return item; + NetworkTransaction *tr = conn->GetTransaction(); + if (tr != nullptr && !tr->IsSending()) + { + currentTransactionSocketNumber = conn->GetNumber(); + return tr; + } + return nullptr; } - previous = item; - } - - // We failed to find a valid transaction for the given connection - return nullptr; -#endif -} -void Network::AppendTransaction(NetworkTransaction* * list, NetworkTransaction *r) -{ - r->next = nullptr; - while (*list != nullptr) - { - list = &((*list)->next); + size_t socketNum = currentTransactionSocketNumber; + do + { + NetworkTransaction *tr = sockets[socketNum].GetTransaction(); + if (tr != nullptr && !tr->IsSending()) + { + currentTransactionSocketNumber = socketNum; + return tr; + } + ++socketNum; + if (socketNum == NumTcpSockets) + { + socketNum = 0; + } + } while (socketNum != currentTransactionSocketNumber); } - *list = r; -} -void Network::PrependTransaction(NetworkTransaction* * list, NetworkTransaction *r) -{ - r->next = *list; - *list = r; + return nullptr; } -void Network::OpenDataPort(uint16_t port) +void Network::OpenDataPort(Port port) { - //TODO -#if 0 - closingDataPort = false; - tcp_pcb* pcb = tcp_new(); - tcp_bind(pcb, IP_ADDR_ANY, port); - ftp_pasv_pcb = tcp_listen(pcb); - tcp_accept(ftp_pasv_pcb, conn_accept); -#endif + sockets[FtpSocketNumber].Init(FtpSocketNumber, port); + sockets[FtpSocketNumber].Poll(false); } -uint16_t Network::GetDataPort() const +Port Network::GetDataPort() const { -#if 1 - return 0; //TODO -#else - return (closingDataPort || (ftp_pasv_pcb == nullptr) ? 0 : ftp_pasv_pcb->local_port); -#endif + return sockets[FtpSocketNumber].GetLocalPort(); } // Close FTP data port and purge associated PCB void Network::CloseDataPort() { - //TODO -#if 0 - // See if it's already being closed - if (closingDataPort) - { - return; - } - closingDataPort = true; - - // Close remote connection of our data port or do it as soon as the last packet has been sent - if (dataCs != nullptr) - { - NetworkTransaction *mySendingTransaction = dataCs->sendingTransaction; - if (mySendingTransaction != nullptr) - { - mySendingTransaction->Close(); - return; - } - } - - // We can close it now, so do it here - if (ftp_pasv_pcb != nullptr) - { - tcp_accept(ftp_pasv_pcb, nullptr); - tcp_close(ftp_pasv_pcb); - ftp_pasv_pcb = nullptr; - } - closingDataPort = false; -#endif -} - -// These methods keep track of our connections in case we need to send to one of them -void Network::SaveDataConnection() -{ -// dataCs = readyTransactions->cs->GetNumber(); + sockets[FtpSocketNumber].Close(); } -void Network::SaveFTPConnection() +bool Network::AcquireFTPTransaction() { -// ftpCs = readyTransactions->cs->GetNumber(); + return AcquireTransaction(FtpSocketNumber); } -void Network::SaveTelnetConnection() +bool Network::AcquireDataTransaction() { -// telnetCs = readyTransactions->cs->GetNumber(); + return AcquireTransaction(FtpDataSocketNumber); } -bool Network::AcquireFTPTransaction() +bool Network::AcquireTelnetTransaction() { -#if 1 - return false; //TODO -#else - return AcquireTransaction(ftpCs); -#endif + return AcquireTransaction(TelnetSocketNumber); } -bool Network::AcquireDataTransaction() +bool Network::AcquireTransaction(SocketNumber skt) { -#if 1 - return false; //TODO -#else - return AcquireTransaction(dataCs); -#endif -} + if ( sockets[skt].GetTransaction() != nullptr + && sockets[skt].GetTransaction()->GetStatus() != TransactionStatus::sending + && sockets[skt].GetTransaction()->GetStatus() != TransactionStatus::finished + ) + { + currentTransactionSocketNumber = skt; + return true; + } -bool Network::AcquireTelnetTransaction() -{ -#if 1 - return false; //TODO -#else - return AcquireTransaction(telnetCs); -#endif + return false; } void Network::InitSockets() @@ -474,7 +383,7 @@ void Network::InitSockets() sockets[FtpSocketNumber].Init(FtpSocketNumber, FTP_PORT); sockets[FtpDataSocketNumber].Init(FtpDataSocketNumber, 0); // FTP data port is allocated dynamically sockets[TelnetSocketNumber].Init(TelnetSocketNumber, TELNET_PORT); - nextSocketToProcess = nextSocketToPoll = 0; + nextSocketToPoll = currentTransactionSocketNumber = 0; } void Network::TerminateSockets() @@ -483,11 +392,23 @@ void Network::TerminateSockets() { sockets[skt].Terminate(); } +} +void Network::Defer(NetworkTransaction *tr) +{ + const Socket *skt = tr->GetConnection(); + if (skt != nullptr && skt->GetNumber() == currentTransactionSocketNumber) + { + ++currentTransactionSocketNumber; + if (currentTransactionSocketNumber == NumTcpSockets) + { + currentTransactionSocketNumber = 0; + } + } } -/*static*/ uint16_t Network::GetLocalPort(Connection conn) { return conn->GetLocalPort(); } -/*static*/ uint16_t Network::GetRemotePort(Connection conn) { return conn->GetRemotePort(); } +/*static*/ Port Network::GetLocalPort(Connection conn) { return conn->GetLocalPort(); } +/*static*/ Port Network::GetRemotePort(Connection conn) { return conn->GetRemotePort(); } /*static*/ uint32_t Network::GetRemoteIP(Connection conn) { return conn->GetRemoteIP(); } /*static*/ bool Network::IsConnected(Connection conn) { return conn->IsConnected(); } /*static*/ bool Network::IsTerminated(Connection conn) { return conn->IsTerminated(); } diff --git a/src/DuetNG/DuetEthernet/Network.h b/src/DuetNG/DuetEthernet/Network.h index d710205a..d6d38555 100644 --- a/src/DuetNG/DuetEthernet/Network.h +++ b/src/DuetNG/DuetEthernet/Network.h @@ -35,7 +35,7 @@ public: void Init(); void Activate(); void Exit(); - void Spin(); + void Spin(bool full); void Diagnostics(MessageType mtype); void Start(); void Stop(); @@ -48,8 +48,8 @@ public: void Disable(); bool IsEnabled() const; - void SetHttpPort(uint16_t port); - uint16_t GetHttpPort() const; + void SetHttpPort(Port port); + Port GetHttpPort() const; void SetHostname(const char *name); @@ -57,20 +57,22 @@ public: NetworkTransaction *GetTransaction(Connection conn = NoConnection); - void OpenDataPort(uint16_t port); - uint16_t GetDataPort() const; + void OpenDataPort(Port port); + Port GetDataPort() const; void CloseDataPort(); - void SaveDataConnection(); - void SaveFTPConnection(); - void SaveTelnetConnection(); + void SaveDataConnection() {} + void SaveFTPConnection() {} + void SaveTelnetConnection() {} bool AcquireFTPTransaction(); bool AcquireDataTransaction(); bool AcquireTelnetTransaction(); - static uint16_t GetLocalPort(Connection conn); - static uint16_t GetRemotePort(Connection conn); + void Defer(NetworkTransaction *tr); + + static Port GetLocalPort(Connection conn); + static Port GetRemotePort(Connection conn); static uint32_t GetRemoteIP(Connection conn); static bool IsConnected(Connection conn); static bool IsTerminated(Connection conn); @@ -86,34 +88,28 @@ private: active }; - void AppendTransaction(NetworkTransaction* * list, NetworkTransaction *r); - void PrependTransaction(NetworkTransaction* * list, NetworkTransaction *r); - bool AcquireTransaction(Socket *cs); + bool AcquireTransaction(SocketNumber skt); void InitSockets(); void TerminateSockets(); Platform *platform; - float longWait; - uint32_t lastTickMillis; - - Socket sockets[NumTcpSockets]; - size_t nextSocketToPoll; // next TCP socket number to poll for read/write operations - size_t nextSocketToProcess; // next TCP socket number to process an incoming request from + float longWait; + uint32_t lastTickMillis; - NetworkTransaction * freeTransactions; - NetworkTransaction * readyTransactions; - NetworkTransaction * writingTransactions; + Socket sockets[NumTcpSockets]; + size_t nextSocketToPoll; // next TCP socket number to poll for read/write operations + size_t currentTransactionSocketNumber; // the socket number of the last transaction we passed to the web server - uint16_t httpPort; + Port httpPort; uint8_t ipAddress[4]; uint8_t netmask[4]; uint8_t gateway[4]; char hostname[16]; // Limit DHCP hostname to 15 characters + terminating 0 NetworkState state; - bool activated; - bool usingDhcp; + bool activated; + bool usingDhcp; }; #endif diff --git a/src/DuetNG/DuetEthernet/NetworkBuffer.cpp b/src/DuetNG/DuetEthernet/NetworkBuffer.cpp index 8fad5241..9bd9697e 100644 --- a/src/DuetNG/DuetEthernet/NetworkBuffer.cpp +++ b/src/DuetNG/DuetEthernet/NetworkBuffer.cpp @@ -6,7 +6,8 @@ */ #include "NetworkBuffer.h" -#include <cstring> + +#include "Storage/FileStore.h" NetworkBuffer *NetworkBuffer::freelist = nullptr; @@ -28,7 +29,7 @@ bool NetworkBuffer::ReadChar(char& b) { if (readPointer < dataLength) { - b = data[readPointer++]; + b = Data()[readPointer++]; return true; } @@ -36,16 +37,15 @@ bool NetworkBuffer::ReadChar(char& b) return false; } -// Read some data, but not more than the amount in the first buffer -size_t NetworkBuffer::ReadBuffer(uint8_t *buffer, size_t maxLen) +const uint8_t* NetworkBuffer::TakeData(size_t &len) { - if (maxLen > Remaining()) + const uint8_t* ret = Data() + readPointer; + if (len > dataLength - readPointer) { - maxLen = Remaining(); + len = dataLength - readPointer; } - memcpy((void*)buffer, data + readPointer, maxLen); - readPointer += maxLen; - return maxLen; + readPointer += len; + return ret; } // Return the amount of data available, including continuation buffers @@ -56,10 +56,52 @@ size_t NetworkBuffer::TotalRemaining() const while (b != nullptr) { ret += b->Remaining(); + b = b->next; } return ret; } +// Append some data, returning the amount appended +size_t NetworkBuffer::AppendData(const uint8_t *source, size_t length) +{ + if (length > SpaceLeft()) + { + length = SpaceLeft(); + } + memcpy(Data() + dataLength, source, length); + dataLength += length; + return length; +} + +// Read into the buffer from a file returning the number of bytes read +int NetworkBuffer::ReadFromFile(FileStore *f) +{ + const int ret = f->Read(reinterpret_cast<char*>(data32), bufferSize); + dataLength = (ret > 0) ? (size_t)ret : 0; + readPointer = 0; + return ret; +} + +// Clear this buffer and release any successors +void NetworkBuffer::Empty() +{ + readPointer = dataLength = 0; + while (next != nullptr) + { + next = next->Release(); + } +} + +/*static*/ void NetworkBuffer::AppendToList(NetworkBuffer **list, NetworkBuffer *b) +{ + b->next = nullptr; + while (*list != nullptr) + { + list = &((*list)->next); + } + *list = b; +} + /*static*/ NetworkBuffer *NetworkBuffer::Allocate() { NetworkBuffer *ret = freelist; @@ -67,6 +109,7 @@ size_t NetworkBuffer::TotalRemaining() const { freelist = ret->next; ret->next = nullptr; + ret->dataLength = ret->readPointer = 0; } return ret; } diff --git a/src/DuetNG/DuetEthernet/NetworkBuffer.h b/src/DuetNG/DuetEthernet/NetworkBuffer.h index 9e20c4bd..63384d89 100644 --- a/src/DuetNG/DuetEthernet/NetworkBuffer.h +++ b/src/DuetNG/DuetEthernet/NetworkBuffer.h @@ -8,8 +8,7 @@ #ifndef SRC_DUETNG_DUETETHERNET_NETWORKBUFFER_H_ #define SRC_DUETNG_DUETETHERNET_NETWORKBUFFER_H_ -#include <cstdint> -#include <cstddef> +#include "RepRapFirmware.h" // Network buffer class. These buffers are 2K long so that they can accept as much data as the W5500 can provide in one go. class NetworkBuffer @@ -24,7 +23,7 @@ public: bool ReadChar(char& b); // Read some data - size_t ReadBuffer(uint8_t *buffer, size_t maxLen); + const uint8_t* TakeData(size_t &len); // Return the amount of data available, not including continuation buffers size_t Remaining() const { return dataLength - readPointer; } @@ -32,21 +31,40 @@ public: // Return the amount of data available, including continuation buffers size_t TotalRemaining() const; + // Return true if there no data left to read bool IsEmpty() const { return readPointer == dataLength; } + // Return the length available for writing + size_t SpaceLeft() const { return bufferSize - dataLength; } + + // Append some data, returning the amount appended + size_t AppendData(const uint8_t *source, size_t length); + + // Read into the buffer from a file + int ReadFromFile(FileStore *f); + + // Clear this buffer and release any successors + void Empty(); + + // Append a buffer to a list + static void AppendToList(NetworkBuffer **list, NetworkBuffer *b); + + // Allocate a buffer static NetworkBuffer *Allocate(); + // Alocate buffers and put them in the freelist static void AllocateBuffers(unsigned int number); static const size_t bufferSize = 2048; private: NetworkBuffer(NetworkBuffer *n); + uint8_t *Data() { return reinterpret_cast<uint8_t*>(data32); } NetworkBuffer *next; size_t dataLength; size_t readPointer; - uint8_t data[bufferSize]; + uint32_t data32[bufferSize/sizeof(uint32_t)]; // 32-bit aligned buffer so we can do direct DMA static NetworkBuffer *freelist; }; diff --git a/src/DuetNG/DuetEthernet/NetworkDefs.h b/src/DuetNG/DuetEthernet/NetworkDefs.h index a1225e63..66bc25c6 100644 --- a/src/DuetNG/DuetEthernet/NetworkDefs.h +++ b/src/DuetNG/DuetEthernet/NetworkDefs.h @@ -1,5 +1,5 @@ /* - * NetworkCommon.h + * NetworkDefs.h * * Created on: 25 Dec 2016 * Author: David @@ -8,6 +8,9 @@ #ifndef SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ #define SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ +#include <cstdint> +#include <cstddef> + class NetworkTransaction; class Socket; class NetworkBuffer; @@ -21,8 +24,8 @@ const SocketNumber NoSocket = 255; typedef uint16_t Port; -const uint8_t DefaultMacAddress[6] = { 0xBE, 0xEF, 0xDE, 0xAD, 0xFE, 0xED }; // Need some sort of default... -const uint8_t DefaultIpAddress[4] = { 0, 0, 0, 0 }; // Need some sort of default... +const uint8_t DefaultMacAddress[6] = { 0xBE, 0xEF, 0xDE, 0xAD, 0xFE, 0xED }; +const uint8_t DefaultIpAddress[4] = { 0, 0, 0, 0 }; const uint8_t DefaultNetMask[4] = { 255, 255, 255, 0 }; const uint8_t DefaultGateway[4] = { 0, 0, 0, 0 }; @@ -32,4 +35,7 @@ const Port TELNET_PORT = 23; const unsigned int TCP_MSS = 1460; +const size_t NetworkTransactionCount = 8; // number of NetworkTransactions to be used for network IO +const size_t NetworkBufferCount = 12; // number of 2K network buffers + #endif /* SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ */ diff --git a/src/DuetNG/DuetEthernet/NetworkTransaction.cpp b/src/DuetNG/DuetEthernet/NetworkTransaction.cpp index 855c4c85..eeeb0e90 100644 --- a/src/DuetNG/DuetEthernet/NetworkTransaction.cpp +++ b/src/DuetNG/DuetEthernet/NetworkTransaction.cpp @@ -6,46 +6,47 @@ */ #include "NetworkTransaction.h" + +#include "Network.h" +#include "RepRap.h" #include "Socket.h" #include <cstdarg> //*************************************************************************************************** // NetworkTransaction class -NetworkTransaction::NetworkTransaction(NetworkTransaction *n) : next(n), status(released) +NetworkTransaction *NetworkTransaction::freelist = nullptr; + +NetworkTransaction::NetworkTransaction(NetworkTransaction *n) + : next(n), fileBuffer(nullptr), sendBuffer(nullptr), sendStack(new OutputStack()), fileBeingSent(nullptr), status(TransactionStatus::released) { - sendStack = new OutputStack(); } -#if 0 -void NetworkTransaction::Set(pbuf *p, ConnectionState *c, TransactionStatus s) +void NetworkTransaction::Set(Socket *skt, TransactionStatus s) { - cs = c; -// pb = readingPb = p; + cs = skt; status = s; -// inputPointer = 0; - sendBuffer = nullptr; - fileBeingSent = nullptr; closeRequested = false; - nextWrite = nullptr; - dataAcknowledged = false; } -#endif bool NetworkTransaction::HasMoreDataToRead() const { - //TODO - return false; + return cs != nullptr && cs->HasMoreDataToRead(); } bool NetworkTransaction::IsConnected() const { - return (cs != nullptr && cs->IsConnected()); + return cs != nullptr && cs->IsConnected(); +} + +bool NetworkTransaction::IsSending() const +{ + return status == TransactionStatus::sending || status == TransactionStatus::finished; } bool NetworkTransaction::CanWrite() const { - return (IsConnected() && status != released); + return status != TransactionStatus::released && cs != nullptr && cs->CanWrite(); } // Read one char from the NetworkTransaction @@ -63,30 +64,7 @@ bool NetworkTransaction::Read(char& b) // Read data from the NetworkTransaction and return true on success bool NetworkTransaction::ReadBuffer(const char *&buffer, size_t &len) { -#if 1 - return false; -#else - if (readingPb == nullptr) - { - return false; - } - - if (inputPointer >= readingPb->len) - { - readingPb = readingPb->next; - inputPointer = 0; - if (readingPb == nullptr) - { - return false; - } - } - - buffer = (const char*)readingPb->payload + inputPointer; - len = readingPb->len - inputPointer; - readingPb = readingPb->next; - inputPointer = 0; - return true; -#endif + return cs != NoConnection && cs->ReadBuffer(buffer, len); } void NetworkTransaction::Write(char b) @@ -182,211 +160,86 @@ void NetworkTransaction::SetFileToWrite(FileStore *file) } else if (file != nullptr) { + debugPrintf("Want to write file but can't write\n"); file->Close(); } } -// Send exactly one TCP window of data and return true when this transaction can be released -bool NetworkTransaction::Send() +// Get some data to send up to the specified length, which must be nonzero. +// A null return means there is nothing left to send or we couldn't allocate a buffer. +// If there was nothing left to send then the status is changed to 'finished'. +const uint8_t *NetworkTransaction::GetDataToSend(size_t& length) { -#if 1 - return true; -#else - // Free up this transaction if the connection is supposed to be closed - if (closeRequested) + // Discard any empty output buffers + while (sendBuffer != nullptr && sendBuffer->BytesLeft() == 0) { - reprap.GetNetwork()->ConnectionClosed(cs, true); // This will release the transaction too - return false; + sendBuffer = OutputBuffer::Release(sendBuffer); + if (sendBuffer == nullptr) + { + sendBuffer = sendStack->Pop(); + } } - // Fill up the TCP window with some data chunks from our OutputBuffer instances - size_t bytesBeingSent = 0, bytesLeftToSend = TCP_WND; - while (sendBuffer != nullptr && bytesLeftToSend > 0) + // If we have an output buffer, send it + if (sendBuffer != nullptr) { - size_t copyLength = min<size_t>(bytesLeftToSend, sendBuffer->BytesLeft()); - memcpy(sendingWindow + bytesBeingSent, sendBuffer->Read(copyLength), copyLength); - bytesBeingSent += copyLength; - bytesLeftToSend -= copyLength; - - if (sendBuffer->BytesLeft() == 0) + if (length > sendBuffer->BytesLeft()) { - sendBuffer = OutputBuffer::Release(sendBuffer); - if (sendBuffer == nullptr) - { - sendBuffer = sendStack->Pop(); - } + length = sendBuffer->BytesLeft(); } + return reinterpret_cast<const uint8_t*>(sendBuffer->Read(length)); } - // We also intend to send a file, so check if we can fill up the TCP window - if (sendBuffer == nullptr && bytesLeftToSend != 0 && fileBeingSent != nullptr) + // If we have a file to send, send it + if (fileBeingSent != nullptr && fileBuffer == nullptr) { - // For HSMCI efficiency, read from the file in multiples of 4 bytes except at the end. - // This ensures that the second and subsequent chunks can be DMA'd directly into sendingWindow. - size_t bytesToRead = bytesLeftToSend & (~3); - if (bytesToRead != 0) + fileBuffer = NetworkBuffer::Allocate(); + if (fileBuffer == nullptr) { - int bytesRead = fileBeingSent->Read(sendingWindow + bytesBeingSent, bytesToRead); - if (bytesRead > 0) - { - bytesBeingSent += bytesRead; - } + return nullptr; // no buffer available + } + } - if (bytesRead != (int)bytesToRead) + // If we have a file buffer here, we must be in the process of sending a file + if (fileBuffer != nullptr) + { + if (fileBuffer->IsEmpty() && fileBeingSent != nullptr) + { + const int bytesRead = fileBuffer->ReadFromFile(fileBeingSent); + if (bytesRead != (int)NetworkBuffer::bufferSize) { fileBeingSent->Close(); fileBeingSent = nullptr; } } - } - if (bytesBeingSent == 0) - { - // If we have no data to send, this connection can be closed next time - if (!cs->persistConnection && nextWrite == nullptr) + if (!fileBuffer->IsEmpty()) { - Close(); - return false; + if (length > fileBuffer->Remaining()) + { + length = fileBuffer->Remaining(); + } + return fileBuffer->TakeData(length); } - // We want to send data from another transaction as well, so only free up this one - cs->sendingTransaction = nextWrite; - return true; - } - - // The TCP window has been filled up as much as possible, so send it now. There is no need to check - // the available space in the SNDBUF queue, because we really write only one TCP window at once. - writeResult = tcp_write(cs->pcb, sendingWindow, bytesBeingSent, 0); - if (ERR_IS_FATAL(writeResult)) - { - reprap.GetPlatform()->MessageF(HOST_MESSAGE, "Network: Failed to write data in Send (code %d)\n", writeResult); - tcp_abort(cs->pcb); - return false; - } - - outputResult = tcp_output(cs->pcb); - if (ERR_IS_FATAL(outputResult)) - { - reprap.GetPlatform()->MessageF(HOST_MESSAGE, "Network: Failed to output data in Send (code %d)\n", outputResult); - tcp_abort(cs->pcb); - return false; - } - - if (outputResult != ERR_OK && reprap.Debug(moduleNetwork)) - { - reprap.GetPlatform()->MessageF(HOST_MESSAGE, "Network: tcp_output resulted in error code %d\n", outputResult); + fileBuffer->Release(); + fileBuffer = nullptr; } - // Set LwIP callbacks for ACK and retransmission handling - tcp_poll(cs->pcb, conn_poll, TCP_WRITE_TIMEOUT / TCP_SLOW_INTERVAL / TCP_MAX_SEND_RETRIES); - tcp_sent(cs->pcb, conn_sent); - - // Set all values for the send process - sendingConnection = cs; - sendingRetries = 0; - sendingWindowSize = sentDataOutstanding = bytesBeingSent; - return false; -#endif + status = TransactionStatus::finished; + return nullptr; } // This is called by the Webserver to send output data to a client. If keepConnectionAlive is set to false, // the current connection will be terminated once everything has been sent. void NetworkTransaction::Commit(bool keepConnectionAlive) { -#if 0 - // If the connection has been terminated (e.g. RST received while writing upload data), discard this transaction - if (!IsConnected() || status == released) - { - Discard(); - return; - } - - // Free buffer holding the incoming data and prepare some values for the sending process - FreePbuf(); - cs->persistConnection = keepConnectionAlive; - if (sendBuffer == nullptr) - { - sendBuffer = sendStack->Pop(); - } - status = sending; - - // Unlink the item(s) from the list of ready transactions - if (keepConnectionAlive) - { - // Our connection is still of interest, remove only this transaction from the list - NetworkTransaction *previous = nullptr; - for(NetworkTransaction *item = reprap.GetNetwork()->readyTransactions; item != nullptr; item = item->next) - { - if (item == this) - { - if (previous == nullptr) - { - reprap.GetNetwork()->readyTransactions = next; - } - else - { - previous->next = next; - } - break; - } - previous = item; - } - } - else - { - // We will close this connection soon, stop receiving data from this PCB - tcp_recv(cs->pcb, nullptr); - - // Also remove all ready transactions pointing to our ConnectionState - NetworkTransaction *previous = nullptr, *item = reprap.GetNetwork()->readyTransactions; - while (item != nullptr) - { - if (item->cs == cs) - { - if (item == this) - { - // Only unlink this item - if (previous == nullptr) - { - reprap.GetNetwork()->readyTransactions = next; - } - else - { - previous->next = next; - } - item = next; - } - else - { - // Remove all others - item->Discard(); - item = (previous == nullptr) ? reprap.GetNetwork()->readyTransactions : previous->next; - } - } - else - { - previous = item; - item = item->next; - } - } - } - - // Enqueue this transaction, so it's sent in the right order - NetworkTransaction *mySendingTransaction = cs->sendingTransaction; - if (mySendingTransaction == nullptr) + closeAfterSending = !keepConnectionAlive; + status = TransactionStatus::sending; + if (closeAfterSending) { - cs->sendingTransaction = this; - reprap.GetNetwork()->AppendTransaction(&reprap.GetNetwork()->writingTransactions, this); + cs->DiscardReceivedData(); } - else - { - while (mySendingTransaction->nextWrite != nullptr) - { - mySendingTransaction = mySendingTransaction->nextWrite; - } - mySendingTransaction->nextWrite = this; - } -#endif } // Call this to perform some networking tasks while processing deferred requests, @@ -397,141 +250,25 @@ void NetworkTransaction::Commit(bool keepConnectionAlive) // This will ensure that zero-window packets are sent back to the client // 2) ResetData: Reset the read pointers and acknowledge that the data has been processed // 3) DiscardData: Free the processed data, acknowledge it and append this transaction as -// an empty item again without payload (i.e. without pbufs) +// an empty item again without payload // void NetworkTransaction::Defer(DeferralMode mode) { -#if 0 - if (mode == DeferralMode::ResetData) - { - // Reset the reading pointers and send an ACK - inputPointer = 0; - readingPb = pb; - if (IsConnected() && pb != nullptr && !dataAcknowledged) - { - tcp_recved(cs->pcb, pb->tot_len); - dataAcknowledged = true; - } - } - else if (mode == DeferralMode::DiscardData) + if (mode == DeferralMode::DiscardData) { - // Discard the incoming data, because we don't need to process it any more - FreePbuf(); + cs->DiscardReceivedData(); // discard the incoming data, because we don't need to process it any more } - status = deferred; - - // Unlink this transaction from the list of ready transactions and append it again - Network *network = reprap.GetNetwork(); - NetworkTransaction *item, *previous = nullptr; - for(item = network->readyTransactions; item != nullptr; item = item->next) - { - if (item == this) - { - if (previous == nullptr) - { - network->readyTransactions = next; - } - else - { - previous->next = next; - } - break; - } - previous = item; - } - network->AppendTransaction(&network->readyTransactions, this); - - // Append all other transactions that are associated to this connection, so that the - // Webserver gets a chance to deal with all connected clients even while multiple - // deferred requests are present in the list. - item = network->readyTransactions; - previous = nullptr; - while (item != this) - { - if (item->cs == cs) - { - NetworkTransaction *nextItem = item->next; - if (previous == nullptr) - { - network->readyTransactions = item->next; - network->AppendTransaction(&network->readyTransactions, item); - } - else - { - previous->next = item->next; - network->AppendTransaction(&network->readyTransactions, item); - } - item = nextItem; - } - else - { - previous = item; - item = item->next; - } - } -#endif + status = TransactionStatus::deferred; + reprap.GetNetwork()->Defer(this); } - // This method should be called if we don't want to send data to the client and if we // don't want to interfere with the connection state. May also be called from ISR! void NetworkTransaction::Discard() { -#if 0 - // Can we do anything? - if (status == released) - { - // No - don't free up released items multiple times - return; - } - - // Free up some resources - FreePbuf(); - - if (fileBeingSent != nullptr) - { - fileBeingSent->Close(); - fileBeingSent = nullptr; - } - - OutputBuffer::ReleaseAll(sendBuffer); - sendStack->ReleaseAll(); - - // Unlink this transactions from the list of ready transactions and free it. It is then appended to the list of - // free transactions because we don't want to risk reusing it when the ethernet ISR processes incoming data - NetworkTransaction *previous = nullptr; - for(NetworkTransaction *item = reprap.GetNetwork()->readyTransactions; item != nullptr; item = item->next) - { - if (item == this) - { - if (previous == nullptr) - { - reprap.GetNetwork()->readyTransactions = next; - } - else - { - previous->next = next; - } - break; - } - previous = item; - } - reprap.GetNetwork()->AppendTransaction(&reprap.GetNetwork()->freeTransactions, this); - bool callDisconnectHandler = (cs != nullptr && status == disconnected); - status = released; - - // Call disconnect event if this transaction indicates a graceful disconnect and if the connection - // still persists (may not be the case if a RST packet was received before) - if (callDisconnectHandler) - { - if (reprap.Debug(moduleNetwork)) - { - reprap.GetPlatform()->Message(HOST_MESSAGE, "Network: Discard() is handling a graceful disconnect\n"); - } - reprap.GetNetwork()->ConnectionClosed(cs, false); - } -#endif + status = TransactionStatus::finished; + cs->ReleaseTransaction(); } uint32_t NetworkTransaction::GetRemoteIP() const @@ -539,23 +276,64 @@ uint32_t NetworkTransaction::GetRemoteIP() const return (cs != nullptr) ? cs->GetRemoteIP() : 0; } -uint16_t NetworkTransaction::GetRemotePort() const +Port NetworkTransaction::GetRemotePort() const { return (cs != nullptr) ? cs->GetRemotePort() : 0; } -uint16_t NetworkTransaction::GetLocalPort() const +Port NetworkTransaction::GetLocalPort() const { return (cs != nullptr) ? cs->GetLocalPort() : 0; } -void NetworkTransaction::Close() +// Create the specified number of buffers and put them on the freelist +/*static*/ void NetworkTransaction::AllocateTransactions(unsigned int number) +{ + if (freelist == nullptr) + { + while (number != 0) + { + freelist = new NetworkTransaction(freelist); + --number; + } + } +} + +// Allocate a buffer from the freelist +/*static*/ NetworkTransaction *NetworkTransaction::Allocate() { -#if 0 - tcp_pcb *pcb = cs->pcb; - tcp_recv(pcb, nullptr); - closeRequested = true; -#endif + NetworkTransaction *ret = freelist; + if (ret != nullptr) + { + freelist = ret->next; + ret->next = nullptr; + ret->fileBuffer = nullptr; + ret->fileBeingSent = nullptr; + } + return ret; +} + +// Free resources and recycle this buffer +NetworkTransaction *NetworkTransaction::Release() +{ + if (fileBuffer != nullptr) + { + fileBuffer->Release(); + fileBuffer = nullptr; + } + if (fileBeingSent != nullptr) + { + fileBeingSent->Close(); + fileBeingSent = nullptr; + } + + OutputBuffer::ReleaseAll(sendBuffer); + sendStack->ReleaseAll(); + + NetworkTransaction *ret = next; + next = freelist; + freelist = this; + return ret; } // End diff --git a/src/DuetNG/DuetEthernet/NetworkTransaction.h b/src/DuetNG/DuetEthernet/NetworkTransaction.h index 93ddc725..0dd5c3cc 100644 --- a/src/DuetNG/DuetEthernet/NetworkTransaction.h +++ b/src/DuetNG/DuetEthernet/NetworkTransaction.h @@ -17,7 +17,7 @@ #include "NetworkBuffer.h" // Assign a status to each NetworkTransaction -enum TransactionStatus +enum class TransactionStatus { released, connected, @@ -25,7 +25,8 @@ enum TransactionStatus sending, disconnected, deferred, - acquired + acquired, + finished }; // How is a deferred request supposed to be handled? @@ -41,14 +42,13 @@ enum class DeferralMode class NetworkTransaction { public: - friend class Network; - NetworkTransaction(NetworkTransaction* n); -// void Set(pbuf *p, ConnectionState* c, TransactionStatus s); + void Set(Socket *skt, TransactionStatus s); TransactionStatus GetStatus() const { return status; } bool IsConnected() const; + bool IsSending() const; - bool HasMoreDataToRead() const; // { return readingPb != nullptr; } + bool HasMoreDataToRead() const; bool Read(char& b); bool ReadBuffer(const char *&buffer, size_t &len); void Write(char b); @@ -65,30 +65,31 @@ public: uint32_t GetRemoteIP() const; Port GetRemotePort() const; - bool Send(); + const uint8_t *GetDataToSend(size_t& length); void Commit(bool keepConnectionAlive); void Defer(DeferralMode mode); void Discard(); + NetworkTransaction *Release(); - NetworkTransaction *GetNext() const { return next; } - NetworkTransaction *GetNextWrite() const { return nextWrite; } + static void AllocateTransactions(unsigned int number); + static NetworkTransaction *Allocate(); private: bool CanWrite() const; - void Close(); - Socket* cs; // the network socket that this transaction cam from + static NetworkTransaction *freelist; + + Socket* cs; // the network socket that this transaction came from NetworkTransaction* next; // next NetworkTransaction in the list we are in - NetworkTransaction* nextWrite; // next NetworkTransaction queued to write to assigned connection -// NetworkBuffer *pb, *readingPb; // received packet queue and a pointer to the pbuf being read from -// size_t inputPointer; // amount of data already taken from the first packet buffer + NetworkBuffer *fileBuffer; // buffer holding the file chunk we are writing OutputBuffer *sendBuffer; OutputStack *sendStack; - FileStore * volatile fileBeingSent; + FileStore *fileBeingSent; - /*volatile*/ TransactionStatus status; - /*volatile*/ bool closeRequested, dataAcknowledged; + TransactionStatus status; + bool closeAfterSending; + bool closeRequested; }; #endif /* SRC_DUETNG_DUETETHERNET_NETWORKTRANSACTION_H_ */ diff --git a/src/DuetNG/DuetEthernet/Socket.cpp b/src/DuetNG/DuetEthernet/Socket.cpp index 7bfff537..9624c56e 100644 --- a/src/DuetNG/DuetEthernet/Socket.cpp +++ b/src/DuetNG/DuetEthernet/Socket.cpp @@ -6,14 +6,15 @@ */ #include "Socket.h" + #include "NetworkTransaction.h" #include "NetworkBuffer.h" -#include <socketlib.h> +#include "socketlib.h" //*************************************************************************************************** // Socket class -Socket::Socket() : receivedData(nullptr), sendingTransaction(nullptr) +Socket::Socket() : currentTransaction(nullptr), receivedData(nullptr) { } @@ -27,29 +28,41 @@ void Socket::Init(SocketNumber skt, Port serverPort) void Socket::ReInit() { - // Discard any transactions that were queued to send - NetworkTransaction *st; - while ((st = sendingTransaction) != nullptr) - { - sendingTransaction = st->GetNext(); - st->Discard(); - } - // Discard any received data while (receivedData != nullptr) { receivedData = receivedData->Release(); } + ReleaseTransaction(); persistConnection = true; isTerminated = false; + isSending = false; state = SocketState::inactive; // Re-initialise the socket on the W5500 +//debugPrintf("About to initialise socket %u\n", socketNum); socket(socketNum, Sn_MR_TCP, localPort, 0x00); +//debugPrintf("Initialised socket %u\n", socketNum); +} + +// Close a connection when the last packet has been sent +void Socket::Close() +{ + disconnectNoWait(socketNum); +} + +// Release the current transaction +void Socket::ReleaseTransaction() +{ + if (currentTransaction != nullptr) + { + currentTransaction->Release(); + currentTransaction = nullptr; + } } -// Terminate a connection +// Terminate a connection immediately void Socket::Terminate() { disconnectNoWait(socketNum); @@ -59,17 +72,43 @@ void Socket::Terminate() { receivedData = receivedData->Release(); } + ReleaseTransaction(); } // Test whether we have a connection on this socket bool Socket::IsConnected() const { - return getSn_SR(socketNum) == SOCK_ESTABLISHED; //TODO is this right? + const uint8_t stat = getSn_SR(socketNum); + return stat == SOCK_ESTABLISHED || stat == SOCK_CLOSE_WAIT; +} + +// Return true if there is or may soon be more data to read +bool Socket::HasMoreDataToRead() const +{ + return (receivedData != nullptr && receivedData->TotalRemaining() != 0) // already have more data + || getSn_SR(socketNum) == SOCK_ESTABLISHED; // still fully connected, so we may receive more +} + +bool Socket::CanWrite() const +{ + const uint8_t stat = getSn_SR(socketNum); + return stat == SOCK_ESTABLISHED || stat == SOCK_CLOSE_WAIT; +} + +// Return true if we are in the sending phase +bool Socket::IsSending() const +{ + return currentTransaction != nullptr && currentTransaction->IsSending(); } // Read 1 character from the receive buffers, returning true if successful bool Socket::ReadChar(char& c) { + while (receivedData != nullptr && receivedData->IsEmpty()) + { + receivedData = receivedData->Release(); // discard empty buffer at head of chain + } + if (receivedData == nullptr) { c = 0; @@ -84,8 +123,27 @@ bool Socket::ReadChar(char& c) return ret; } +// Return a pointer to data in a buffer and a length available, and mark the data as taken +bool Socket::ReadBuffer(const char *&buffer, size_t &len) +{ + while (receivedData != nullptr && receivedData->IsEmpty()) + { + receivedData = receivedData->Release(); // discard empty buffer at head of chain + } + + if (receivedData == nullptr) + { + return false; + } + + len = 2048; // initial value passed to TakeData is the maximum amount we will take + buffer = reinterpret_cast<const char*>(receivedData->TakeData(len)); +// debugPrintf("Taking %d bytes\n", len); + return true; +} + // Poll a socket to see if it needs to be serviced -void Socket::Poll() +void Socket::Poll(bool full) { switch(getSn_SR(socketNum)) { @@ -93,7 +151,7 @@ void Socket::Poll() // Socket has been initialised but is not listening yet if (localPort != 0) // localPort for the FTP data socket is 0 until we have decided what port number to use { - listen(socketNum); + ExecCommand(socketNum, Sn_CR_LISTEN); } break; @@ -114,32 +172,57 @@ void Socket::Poll() const uint16_t len = getSn_RX_RSR(socketNum); if (len != 0) { +// debugPrintf("%u available\n", len); // There is data available, so allocate a buffer NetworkBuffer * const buf = NetworkBuffer::Allocate(); if (buf != nullptr) { - buf->dataLength = recv(socketNum, buf->data, min<size_t>(len, NetworkBuffer::bufferSize)); - buf->readPointer = 0; - // Append the buffer to the list of receive buffers - NetworkBuffer** bufp = &receivedData; - while (*bufp != nullptr) + const int32_t ret = recv(socketNum, buf->Data(), min<size_t>(len, NetworkBuffer::bufferSize)); +// debugPrintf("ret %d\n", ret); + if (ret > 0) + { + buf->dataLength = (size_t)ret; + buf->readPointer = 0; + NetworkBuffer::AppendToList(&receivedData, buf); + } + else { - bufp = &((*bufp)->next); + buf->Release(); +// debugPrintf("Bad receive, code = %d\n", ret); } - *bufp = buf; + } + else debugPrintf("no buffer\n"); + } + + if (receivedData != nullptr && currentTransaction == nullptr) + { + currentTransaction = NetworkTransaction::Allocate(); + if (currentTransaction != nullptr) + { + currentTransaction->Set(this, TransactionStatus::receiving); } } } - // See if we can send any data - //TODO + // See if we can send any data. + // Currently we don't send if we are being called from hsmci because we don't want to risk releasing a buffer that we may be reading data into. + // We could use a buffer locking mechanism instead. However, the speed of sending is not critical, so we don't do that yet. + if (full && IsSending() && TrySendData()) + { + ReleaseTransaction(); + ExecCommand(socketNum, Sn_CR_DISCON); + } break; case SOCK_CLOSE_WAIT: // A client has asked to disconnect #ifdef _HTTPSERVER_DEBUG_ printf("> HTTPSocket[%d] : ClOSE_WAIT\r\n", socketNum); #endif - disconnect(socketNum); + if (!IsSending() || TrySendData()) + { + ReleaseTransaction(); + ExecCommand(socketNum, Sn_CR_DISCON); + } break; case SOCK_CLOSED: @@ -163,4 +246,76 @@ void Socket::Poll() #endif } +// Try to send data, returning true if all data has been sent and we ought to close the socket +// We have already checked that the socket is in the ESTABLISHED or CLOSE_WAIT state. +bool Socket::TrySendData() +{ + if (isSending) // are we already sending? + { + const uint8_t tmp = getSn_IR(socketNum); + if (tmp & Sn_IR_SENDOK) // did the previous send complete? + { + setSn_IR(socketNum, Sn_IR_SENDOK); // if yes + isSending = false; + } + else if(tmp & Sn_IR_TIMEOUT) // did it time out? + { + isSending = false; + disconnectNoWait(socketNum); // if so, close the socket + return true; // and release buffers etc. + } + else + { + //debugPrintf("Waiting for data to be sent\n"); + return false; // last send is still in progress + } + } + + // Socket is free to send + if (currentTransaction->GetStatus() == TransactionStatus::finished) + { + return true; + } + + size_t freesize = (size_t)getSn_TX_FSR(socketNum); + uint16_t ptr = getSn_TX_WR(socketNum); + bool sent = false; + while (freesize != 0) + { + size_t length = freesize; + const uint8_t *data = currentTransaction->GetDataToSend(length); + if (data == nullptr) + { + break; // no more data or can't allocate a file buffer + } + //debugPrintf("rp=%04x tp=%04x\n", getSn_TX_RD(socketNum), getSn_TX_WR(socketNum)); + wiz_send_data_at(socketNum, data, length, ptr); + //debugPrintf("Wrote %u bytes of %u free, %02x %02x %02x\n", length, freesize, data[0], data[1], data[2]); + freesize -= length; + ptr += (uint16_t)length; + sent = true; + } + if (sent) + { + //debugPrintf("Sending data, rp=%04x tp=%04x\n", getSn_TX_RD(socketNum), getSn_TX_WR(socketNum)); + ExecCommand(socketNum, Sn_CR_SEND); + isSending = true; + } + else if (currentTransaction->GetStatus() == TransactionStatus::finished) + { + return true; // there was no more data to send + } + + return false; +} + +// Discard any received data for this transaction +void Socket::DiscardReceivedData() +{ + while (receivedData != nullptr) + { + receivedData = receivedData->Release(); + } +} + // End diff --git a/src/DuetNG/DuetEthernet/Socket.h b/src/DuetNG/DuetEthernet/Socket.h index 59f04906..7c6ef596 100644 --- a/src/DuetNG/DuetEthernet/Socket.h +++ b/src/DuetNG/DuetEthernet/Socket.h @@ -8,9 +8,8 @@ #ifndef SRC_DUETNG_DUETETHERNET_SOCKET_H_ #define SRC_DUETNG_DUETETHERNET_SOCKET_H_ -#include <NetworkDefs.h> -#include <cstdint> -#include <cstddef> +#include "RepRapFirmware.h" +#include "NetworkDefs.h" // Socket structure that we use to track TCP connections class Socket @@ -18,15 +17,23 @@ class Socket public: Socket(); void Init(SocketNumber s, Port serverPort); - void Poll(); + void Poll(bool full); Port GetLocalPort() const { return localPort; } uint32_t GetRemoteIP() const { return remoteIPAddress; } Port GetRemotePort() const { return remotePort; } bool IsConnected() const; bool IsTerminated() const { return isTerminated; } + void Close(); void Terminate(); SocketNumber GetNumber() const { return socketNum; } + NetworkTransaction *GetTransaction() const { return currentTransaction; } bool ReadChar(char& c); + bool ReadBuffer(const char *&buffer, size_t &len); + bool HasMoreDataToRead() const; + void ReleaseTransaction(); + bool IsPersistentConnection() const { return persistConnection; } + bool CanWrite() const; + void DiscardReceivedData(); private: enum class SocketState : uint8_t @@ -40,15 +47,20 @@ private: }; void ReInit(); + bool IsSending() const; // Return true if we are in the sending phase + + bool TrySendData() // Try to send data, returning true if all data has been sent and we ought to close the socket + pre(IsSending()); Port localPort, remotePort; // The local and remote ports uint32_t remoteIPAddress; // The remote IP address - NetworkBuffer *receivedData; // Chain of buffers holding received data - NetworkTransaction * /*volatile*/ sendingTransaction; // NetworkTransaction that is currently sending via this connection + NetworkTransaction *currentTransaction; // The transaction currently being processed on this socket + NetworkBuffer *receivedData; // List of buffers holding received data bool persistConnection; // Do we expect this connection to stay alive? bool isTerminated; // Will be true if the connection has gone down unexpectedly (TCP RST) SocketNumber socketNum; // The W5500 socket number we are using SocketState state; + bool isSending; }; #endif /* SRC_DUETNG_DUETETHERNET_SOCKET_H_ */ diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.cpp b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.cpp index 3fab829e..9c7b415e 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.cpp +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.cpp @@ -66,7 +66,7 @@ uint8_t WIZCHIP_READ(uint32_t AddrSel) { WizSpi::AssertSS(); WizSpi::SendAddress(AddrSel | (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_)); - const uint8_t ret = WizSpi::ExchangeByte(0xFF, true); + const uint8_t ret = WizSpi::ReadByte(); WizSpi::ReleaseSS(); return ret; } @@ -75,7 +75,7 @@ void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) { WizSpi::AssertSS(); WizSpi::SendAddress(AddrSel | (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_)); - WizSpi::ExchangeByte(wb, true); + WizSpi::WriteByte(wb); WizSpi::ReleaseSS(); } @@ -112,7 +112,6 @@ uint16_t getSn_TX_FSR(uint8_t sn) return val; } - uint16_t getSn_RX_RSR(uint8_t sn) { uint16_t val = 0, val1 = 0; @@ -134,8 +133,23 @@ void wiz_send_data(uint8_t sn, const uint8_t *wizdata, uint16_t len) if (len != 0) { uint16_t ptr = getSn_TX_WR(sn); - uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - WIZCHIP_WRITE_BUF(addrsel,wizdata, len); + const uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); + WIZCHIP_WRITE_BUF(addrsel, wizdata, len); + + ptr += len; + setSn_TX_WR(sn, ptr); + } +} + +// Function wiz_send_data doesn't work properly when we send TCP/IP data in multiple chunks, +// because the getSn_TX_WR call doesn't read back the incremented value after we wrote to it. +// So use this instead. +void wiz_send_data_at(uint8_t sn, const uint8_t *wizdata, uint16_t len, uint16_t ptr) +{ + if (len != 0) + { + const uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); + WIZCHIP_WRITE_BUF(addrsel, wizdata, len); ptr += len; setSn_TX_WR(sn,ptr); @@ -147,7 +161,7 @@ void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) if (len != 0) { uint16_t ptr = getSn_RX_RD(sn); - uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); + const uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); WIZCHIP_READ_BUF(addrsel, wizdata, len); ptr += len; diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h index 495772ac..805a9811 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h @@ -2268,6 +2268,9 @@ static inline uint16_t getSn_TxMAX(uint8_t sn) */ void wiz_send_data(uint8_t sn, const uint8_t *wizdata, uint16_t len); +// Alternative to wiz_send_data to work around an apparent bug +void wiz_send_data_at(uint8_t sn, const uint8_t *wizdata, uint16_t len, uint16_t ptr); + /** * @ingroup Basic_IO_function * @brief It copies data to your buffer from internal RX memory diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp index c32a14a5..70ebf1d4 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp @@ -25,7 +25,7 @@ #include "matrix.h" // Functions called by the W5500 module to transfer data to/from the W5500 via SPI -const uint32_t SpiClockFrequency = 10000000; // use 10MHz for now, increase it later +const uint32_t SpiClockFrequency = 40000000; const unsigned int SpiPeripheralChannelId = 0; // we use NPCS0 as the slave select signal #if USE_PDC @@ -283,7 +283,7 @@ namespace WizSpi static inline bool waitForTxReady() { uint32_t timeout = SPI_TIMEOUT; - while (!spi_is_tx_ready(SPI)) + while ((SPI->SPI_SR & SPI_SR_TDRE) == 0) { if (--timeout == 0) { @@ -297,7 +297,7 @@ namespace WizSpi static inline bool waitForTxEmpty() { uint32_t timeout = SPI_TIMEOUT; - while (!spi_is_tx_empty(SPI)) + while ((SPI->SPI_SR & SPI_SR_TXEMPTY) == 0) { if (!timeout--) { @@ -311,7 +311,7 @@ namespace WizSpi static inline bool waitForRxReady() { uint32_t timeout = SPI_TIMEOUT; - while (!spi_is_rx_ready(SPI)) + while ((SPI->SPI_SR & SPI_SR_RDRF) == 0) { if (--timeout == 0) { @@ -326,6 +326,7 @@ namespace WizSpi { spi_set_peripheral_chip_select_value(SPI, spi_get_pcs(SpiPeripheralChannelId)); digitalWrite(SamCsPin, LOW); + (void)SPI->SPI_RDR; // clear receive register } // Set the SS pin high again @@ -335,53 +336,79 @@ namespace WizSpi digitalWrite(SamCsPin, HIGH); } + // Send the 3-byte address and control bits. On return there may be data still being received. void SendAddress(uint32_t addr) { - (void)ExchangeByte((uint8_t)(addr >> 16), false); - (void)ExchangeByte((uint8_t)(addr >> 8), false); - (void)ExchangeByte((uint8_t)addr, false); + uint32_t dout = (addr >> 16) & 0x000000FF; + if (!waitForTxReady()) + { + SPI->SPI_TDR = dout; + (void)SPI->SPI_RDR; + dout = (addr >> 8) & 0x000000FF; + if (!waitForTxReady()) + { + SPI->SPI_TDR = dout; + (void)SPI->SPI_RDR; + dout = addr & 0x000000FF; + if (!waitForTxReady()) + { + SPI->SPI_TDR = dout; + (void)SPI->SPI_RDR; + } + } + } } - uint8_t ExchangeByte(uint8_t b, bool isLast) + // Read a single byte. Called after sending the 3-byte address. + uint8_t ReadByte() { - if (waitForTxReady()) + (void)SPI->SPI_RDR; + if (!waitForTxEmpty()) { - return 0; + while ((SPI->SPI_SR & SPI_SR_RDRF) != 0) + { + (void)SPI->SPI_RDR; // clear previous data + } + SPI->SPI_TDR = 0x000000FF | SPI_TDR_LASTXFER; + if (!waitForRxReady()) + { + return (uint8_t)SPI->SPI_RDR; + } } + return 0; + } - // Write to transmit register - uint32_t dOut = b; - if (isLast) + // Write a single byte. Called after sending the address. + void WriteByte(uint8_t b) + { + const uint32_t dOut = b | SPI_TDR_LASTXFER; + if (!waitForTxReady()) { - dOut |= SPI_TDR_LASTXFER; + SPI->SPI_TDR = dOut; } - SPI->SPI_TDR = dOut; + } - // Wait for receive register - if (waitForRxReady()) + spi_status_t ReadBurst(uint8_t* rx_data, size_t len) + { + if (waitForTxEmpty()) { - return 0; + return SPI_ERROR_TIMEOUT; } - // Get data from receive register - return (uint8_t)SPI->SPI_RDR; - } + while ((SPI->SPI_SR & SPI_SR_RDRF) != 0) + { + (void)SPI->SPI_RDR; // clear previous data + } - spi_status_t ReadBurst(uint8_t* rx_data, size_t len) - { for (size_t i = 0; i < len; ++i) { - uint32_t dOut = 0x000000FF; + const uint32_t dOut = ((i + 1) == len) ? 0x000000FF | SPI_TDR_LASTXFER : 0x000000FF; if (waitForTxReady()) { return SPI_ERROR_TIMEOUT; } // Write to transmit register - if (i + 1 == len) - { - dOut |= SPI_TDR_LASTXFER; - } SPI->SPI_TDR = dOut; // Wait for receive register @@ -402,16 +429,17 @@ namespace WizSpi for (uint32_t i = 0; i < len; ++i) { uint32_t dOut = (uint32_t)*tx_data++; + if (i + 1 == len) + { + dOut |= SPI_TDR_LASTXFER; + } + if (waitForTxReady()) { return SPI_ERROR_TIMEOUT; } // Write to transmit register - if (i + 1 == len) - { - dOut |= SPI_TDR_LASTXFER; - } SPI->SPI_TDR = dOut; // Wait for receive register if (waitForRxReady()) diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h index 2829e168..21a5eadc 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h @@ -17,7 +17,8 @@ namespace WizSpi void AssertSS(); void ReleaseSS(); void SendAddress(uint32_t addr); - uint8_t ExchangeByte(uint8_t b, bool isLast); + uint8_t ReadByte(); + void WriteByte(uint8_t b); spi_status_t ReadBurst(uint8_t* rx_data, size_t len); spi_status_t SendBurst(const uint8_t* tx_data, size_t len); } diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp index 0ad63a22..b1d60e4b 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp @@ -92,7 +92,7 @@ uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; if(len == 0) return SOCKERR_DATALEN; \ }while(0); \ -static void ExecCommand(uint8_t sn, uint8_t cmd) +void ExecCommand(uint8_t sn, uint8_t cmd) { setSn_CR(sn, cmd); while(getSn_CR(sn) != 0) { } @@ -207,7 +207,6 @@ int8_t listen(uint8_t sn) return SOCK_OK; } - int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) { CHECK_SOCKMODE(Sn_MR_TCP); diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.h b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.h index 5cd57c57..37f4bf42 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.h +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.h @@ -481,4 +481,7 @@ int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg); */ int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg); +// Execute a command +void ExecCommand(uint8_t sn, uint8_t cmd); + #endif // _SOCKET_H_ diff --git a/src/DuetNG/DuetWiFi/Network.cpp b/src/DuetNG/DuetWiFi/Network.cpp index 03e8f1d3..7127433f 100644 --- a/src/DuetNG/DuetWiFi/Network.cpp +++ b/src/DuetNG/DuetWiFi/Network.cpp @@ -165,7 +165,7 @@ void Network::Stop() } } -void Network::Spin() +void Network::Spin(bool full) { // static float lastTime = 0.0; @@ -176,14 +176,17 @@ void Network::Spin() switch (state) { case starting: - // See if the ESP8266 has set CS high yet - if (digitalRead(SamCsPin)) + if (full) { - // Setup the SPI controller in slave mode and assign the CS pin to it - platform->Message(HOST_MESSAGE, "WiFi server starting up\n"); - SetupSpi(); // set up the SPI subsystem - state = idle; - TryStartTransfer(); + // See if the ESP8266 has set CS high yet + if (digitalRead(SamCsPin)) + { + // Setup the SPI controller in slave mode and assign the CS pin to it + platform->Message(HOST_MESSAGE, "WiFi server starting up\n"); + SetupSpi(); // set up the SPI subsystem + state = idle; + TryStartTransfer(); + } } break; @@ -242,7 +245,7 @@ void Network::Spin() state = sending; // no break case sending: - if (outBuffer.IsEmpty()) + if (full && outBuffer.IsEmpty()) { // See if we have more of the current response to send if (responseBody != nullptr) @@ -368,7 +371,10 @@ void Network::Spin() break; case disabled: - uploader->Spin(); + if (full) + { + uploader->Spin(); + } break; default: diff --git a/src/DuetNG/DuetWiFi/Network.h b/src/DuetNG/DuetWiFi/Network.h index 3258c34a..66963776 100644 --- a/src/DuetNG/DuetWiFi/Network.h +++ b/src/DuetNG/DuetWiFi/Network.h @@ -49,7 +49,7 @@ public: void Init(); void Activate(); void Exit(); - void Spin(); + void Spin(bool full); void SpiInterrupt(); void Diagnostics(MessageType mtype); void Start(); diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h index b01c8099..8294ea12 100644 --- a/src/DuetNG/Pins_DuetNG.h +++ b/src/DuetNG/Pins_DuetNG.h @@ -2,23 +2,27 @@ #define PINS_DUETNG_H__ #if defined(DUET_WIFI) + # define FIRMWARE_NAME "RepRapFirmware for Duet WiFi" +# define DEFAULT_BOARD_TYPE BoardType::DuetWiFi_10 +const size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manual upload to WiFi module +# define IAP_FIRMWARE_FILE "DuetWiFiFirmware.bin" +# define WIFI_FIRMWARE_FILE "DuetWiFiServer.bin" +# define WIFI_WEB_FILE "DuetWebControl.bin" + #elif defined(DUET_ETHERNET) + # define FIRMWARE_NAME "RepRapFirmware for Duet Ethernet" +# define DEFAULT_BOARD_TYPE BoardType::DuetEthernet_10 +# define IAP_FIRMWARE_FILE "DuetEthernetFirmware.bin" +const size_t NumFirmwareUpdateModules = 1; // 1 module + #else # error Firmware name not defined #endif -const size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manual upload to WiFi module -#define IAP_UPDATE_FILE "iap4e.bin" -#define IAP_FIRMWARE_FILE "DuetWiFiFirmware.bin" -#define WIFI_FIRMWARE_FILE "DuetWiFiServer.bin" -#define WIFI_WEB_FILE "DuetWebControl.bin" - -// Default board type -#define DEFAULT_BOARD_TYPE BoardType::DuetWiFi_10 +#define IAP_UPDATE_FILE "iap4e.bin" // hoping eventually to use the same IAP file for both Duet WiFi and Duet Ethernet -#define SUPPORT_ETHERNET 0 // set nonzero to support embedded web interface over Ethernet #define SUPPORT_INKJET 0 // set nonzero to support inkjet control #define SUPPORT_ROLAND 0 // set nonzero to support Roland mill diff --git a/src/GCodes/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer.cpp index fcc8d3a1..1db905bb 100644 --- a/src/GCodes/GCodeBuffer.cpp +++ b/src/GCodes/GCodeBuffer.cpp @@ -401,6 +401,7 @@ bool GCodeBuffer::PushState() ms->drivesRelative = machineState->drivesRelative; ms->axesRelative = machineState->axesRelative; ms->doingFileMacro = machineState->doingFileMacro; + ms->fileState.CopyFrom(machineState->fileState); ms->lockedResources = machineState->lockedResources; machineState = ms; return true; diff --git a/src/GCodes/GCodeMachineState.cpp b/src/GCodes/GCodeMachineState.cpp index 55475680..e21cddfb 100644 --- a/src/GCodes/GCodeMachineState.cpp +++ b/src/GCodes/GCodeMachineState.cpp @@ -12,7 +12,7 @@ unsigned int GCodeMachineState::numAllocated = 0; // Create a default initialised GCodeMachineState GCodeMachineState::GCodeMachineState() - : previous(nullptr), feedrate(DEFAULT_FEEDRATE/minutesToSeconds), fileState(), lockedResources(0), state(GCodeState::normal), + : previous(nullptr), feedrate(DefaultFeedrate * secondsToMinutes), fileState(), lockedResources(0), state(GCodeState::normal), drivesRelative(false), axesRelative(false), doingFileMacro(false), runningM502(false) { } diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index fe84e7f3..1023b08a 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -55,7 +55,7 @@ void GCodes::RestorePoint::Init() { moveCoords[i] = 0.0; } - feedRate = DEFAULT_FEEDRATE/minutesToSeconds; + feedRate = DefaultFeedrate/minutesToSeconds; } GCodes::GCodes(Platform* p, Webserver* w) : @@ -107,8 +107,9 @@ void GCodes::Init() } lastDefaultFanSpeed = 0.0; - retractLength = retractExtra = retractHop = 0.0; - retractSpeed = unRetractSpeed = 600.0; + retractLength = retractExtra = DefaultRetractLength; + retractHop = 0.0; + retractSpeed = unRetractSpeed = DefaultRetractSpeed * secondsToMinutes; isRetracted = false; } @@ -332,7 +333,7 @@ void GCodes::Spin() { moveBuffer.coords[drive] = 0.0; } - moveBuffer.feedRate = DEFAULT_FEEDRATE/minutesToSeconds; // ask for a good feed rate, we may have paused during a slow move + moveBuffer.feedRate = DefaultFeedrate/minutesToSeconds; // ask for a good feed rate, we may have paused during a slow move moveBuffer.moveType = 0; moveBuffer.endStopsToCheck = 0; moveBuffer.usePressureAdvance = false; @@ -926,7 +927,7 @@ bool GCodes::LockMovementAndWaitForStandstill(const GCodeBuffer& gb) // Save (some of) the state of the machine for recovery in the future. bool GCodes::Push(GCodeBuffer& gb) { - bool ok = gb.PushState(); + const bool ok = gb.PushState(); if (!ok) { platform->Message(GENERIC_MESSAGE, "Push(): stack overflow!\n"); @@ -1488,7 +1489,7 @@ bool GCodes::OffsetAxes(GCodeBuffer& gb) } else { - cannedFeedRate = DEFAULT_FEEDRATE; + cannedFeedRate = DefaultFeedrate; } offSetSet = true; @@ -3035,8 +3036,8 @@ bool GCodes::RetractFilament(GCodeBuffer& gb, bool retract) // Set the feed rate. If there is any Z hop then we need to pass the Z speed, else we pass the extrusion speed. const float speedToUse = (retract) ? retractSpeed : unRetractSpeed; moveBuffer.feedRate = (retractHop == 0.0) - ? speedToUse * secondsToMinutes - : speedToUse * secondsToMinutes * retractHop/retractLength; + ? speedToUse + : speedToUse * retractHop/retractLength; moveBuffer.coords[Z_AXIS] += (retract) ? retractHop : -retractHop; const float lengthToUse = (retract) ? -retractLength : retractLength + retractExtra; for (size_t i = 0; i < nDrives; ++i) diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index cce862fe..e8a9131d 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -1603,19 +1603,19 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply) retractLength = max<float>(gb.GetFValue(), 0.0); seen = true; } - if (gb.Seen('R')) + if (gb.Seen('R')) // must do this one after 'S' { retractExtra = max<float>(gb.GetFValue(), -retractLength); seen = true; } if (gb.Seen('F')) { - unRetractSpeed = retractSpeed = max<float>(gb.GetFValue(), 60.0); + unRetractSpeed = retractSpeed = max<float>(gb.GetFValue(), 60.0) * secondsToMinutes; seen = true; } if (gb.Seen('T')) // must do this one after 'F' { - unRetractSpeed = max<float>(gb.GetFValue(), 60.0); + unRetractSpeed = max<float>(gb.GetFValue(), 60.0) * secondsToMinutes; seen = true; } if (gb.Seen('Z')) @@ -1625,8 +1625,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply) } if (!seen) { - reply.printf("Retraction settings: length %.2f/%.2fmm, speed %d/%dmm/min, Z hop %.2fmm", - retractLength, retractLength + retractExtra, (int)retractSpeed, (int)unRetractSpeed, retractHop); + reply.printf("Retraction/un-retraction settings: length %.2f/%.2fmm, speed %d/%dmm/min, Z hop %.2fmm", + retractLength, retractLength + retractExtra, (int)(retractSpeed * minutesToSeconds), (int)(unRetractSpeed * minutesToSeconds), retractHop); } } break; diff --git a/src/Platform.cpp b/src/Platform.cpp index 9f686279..3e9cd452 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -2550,8 +2550,10 @@ void Platform::SetBoardType(BoardType bt) { if (bt == BoardType::Auto) { -#ifdef DUET_NG +#if defined(DUET_NG) && defined(DUET_WIFI) board = BoardType::DuetWiFi_10; +#elif defined(DUET_NG) && defined(DUET_ETHERNET) + board = BoardType::DuetEthernet_10; #elif defined(__RADDS__) board = BoardType::RADDS_15; #else @@ -2581,8 +2583,10 @@ const char* Platform::GetElectronicsString() const { switch (board) { -#ifdef DUET_NG +#if defined(DUET_NG) && defined(DUET_WIFI) case BoardType::DuetWiFi_10: return "Duet WiFi 1.0"; +#elif defined(DUET_NG) && defined(DUET_ETHERNET) + case BoardType::DuetEthernet_10: return "Duet Ethernet 1.0"; #elif defined(__RADDS__) case BoardType::RADDS_15: return "RADDS 1.5"; #else @@ -2599,8 +2603,10 @@ const char* Platform::GetBoardString() const { switch (board) { -#ifdef DUET_NG +#if defined(DUET_NG) && defined(DUET_WIFI) case BoardType::DuetWiFi_10: return "duetwifi10"; +#elif defined(DUET_NG) && defined(DUET_ETHERNET) + case BoardType::DuetEthernet_10: return "duetethernet10"; #elif defined(__RADDS__) case BoardType::RADDS_15: return "radds15"; #else diff --git a/src/Platform.h b/src/Platform.h index cbbd4ec2..aec4f3d0 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -121,8 +121,10 @@ const size_t FILE_BUFFER_SIZE = 256; enum class BoardType : uint8_t { Auto = 0, -#ifdef DUET_NG +#if defined(DUET_NG) && defined(DUET_WIFI) DuetWiFi_10 = 1 +#elif defined(DUET_NG) && defined(DUET_ETHERNET) + DuetEthernet_10 = 1 #elif defined(__RADDS__) RADDS_15 = 1 #else diff --git a/src/RADDS/Network.h b/src/RADDS/Network.h index 4f91e86e..32f5ce31 100644 --- a/src/RADDS/Network.h +++ b/src/RADDS/Network.h @@ -19,7 +19,7 @@ public: void Disable() const { }; void Enable() const { }; void Exit() const { } - void Spin() const { }; + void Spin(bool full) const { }; void Interrupt() const { }; void Diagnostics(MessageType mtype) const { }; diff --git a/src/Reprap.cpp b/src/Reprap.cpp index 6459c801..b758e9ab 100644 --- a/src/Reprap.cpp +++ b/src/Reprap.cpp @@ -10,6 +10,19 @@ #include "Webserver.h" #include "Version.h" +#ifndef __RADDS__ +# include "sam/drivers/hsmci/hsmci.h" +#endif + +// Callback function from the hsmci driver, called while it is waiting for an SD card operation to complete +extern "C" void hsmciIdle() +{ + if (reprap.GetSpinningModule() != moduleNetwork) // I don't think this should ever be false because the Network module doesn't do file access, but just in case... + { + reprap.GetNetwork()->Spin(false); + } +} + // RepRap member functions. // Do nothing more in the constructor; put what you want in RepRap:Init() @@ -103,6 +116,9 @@ void RepRap::Init() } #endif +#ifndef __RADDS__ + hsmci_set_idle_func(hsmciIdle); +#endif platform->MessageF(HOST_MESSAGE, "%s is up and running.\n", FIRMWARE_NAME); fastLoop = FLT_MAX; slowLoop = 0.0; @@ -132,7 +148,7 @@ void RepRap::Spin() spinningModule = moduleNetwork; ticksInSpinState = 0; - network->Spin(); + network->Spin(true); spinningModule = moduleWebserver; ticksInSpinState = 0; diff --git a/src/Version.h b/src/Version.h index 5f7a3706..98641268 100644 --- a/src/Version.h +++ b/src/Version.h @@ -13,7 +13,7 @@ #endif #ifndef DATE -# define DATE "2016-12-25" +# define DATE "2016-12-29" #endif #define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman" diff --git a/src/Webserver/Webserver.cpp b/src/Webserver/Webserver.cpp index 15d34e5e..72e62ca2 100644 --- a/src/Webserver/Webserver.cpp +++ b/src/Webserver/Webserver.cpp @@ -96,12 +96,7 @@ const char* overflowResponse = "overflow"; const char* badEscapeResponse = "bad escape"; -//******************************************************************************************** -// //**************************** Generic Webserver implementation ****************************** -// -//******************************************************************************************** - // Constructor and initialisation Webserver::Webserver(Platform* p, Network *n) : platform(p), network(n), webserverActive(false) @@ -154,7 +149,7 @@ void Webserver::Spin() { // Take care of different protocol types here ProtocolInterpreter *interpreter; - uint16_t localPort = currentTransaction->GetLocalPort(); + const uint16_t localPort = currentTransaction->GetLocalPort(); switch (localPort) { case FTP_PORT: /* FTP */ @@ -183,13 +178,13 @@ void Webserver::Spin() const char *type; switch (currentTransaction->GetStatus()) { - case released: type = "released"; break; - case connected: type = "connected"; break; - case receiving: type = "receiving"; break; - case sending: type = "sending"; break; - case disconnected: type = "disconnected"; break; - case deferred: type = "deferred"; break; - case acquired: type = "acquired"; break; + case TransactionStatus::released: type = "released"; break; + case TransactionStatus::connected: type = "connected"; break; + case TransactionStatus::receiving: type = "receiving"; break; + case TransactionStatus::sending: type = "sending"; break; + case TransactionStatus::disconnected: type = "disconnected"; break; + case TransactionStatus::deferred: type = "deferred"; break; + case TransactionStatus::acquired: type = "acquired"; break; default: type = "unknown"; break; } platform->MessageF(HOST_MESSAGE, "Incoming transaction: Type %s at local port %d (remote port %d)\n", @@ -198,13 +193,13 @@ void Webserver::Spin() // For protocols other than HTTP it is important to send a HELO message TransactionStatus status = currentTransaction->GetStatus(); - if (status == connected) + if (status == TransactionStatus::connected) { interpreter->ConnectionEstablished(); } // Graceful disconnects are handled here, because prior NetworkTransactions might still contain valid // data. That's why it's a bad idea to close these connections immediately in the Network class. - else if (status == disconnected) + else if (status == TransactionStatus::disconnected) { // This will call the disconnect events and effectively close the connection currentTransaction->Discard(); @@ -561,7 +556,7 @@ void Webserver::HttpInterpreter::Spin() // Verify HTTP sessions const uint32_t now = millis(); - for(int i = numSessions - 1; i >= 0; i--) + for(int i = (int)numSessions - 1; i >= 0; i--) { if (sessions[i].isPostUploading) { @@ -624,10 +619,15 @@ void Webserver::HttpInterpreter::DoFastUpload() { network->Unlock(); // Write data in sector-aligned chunks. This also means that the buffer in fatfs is only used to hold the FAT. - static const size_t writeBufLength = 2048; // use a multiple of the 512b sector size + // Buffer size must be a multiple of the 512b sector size. +#ifdef DUET_NG + static const size_t writeBufLength = 4096; +#else + static const size_t writeBufLength = 2048; +#endif static uint32_t writeBufStorage[writeBufLength/4]; // aligned buffer for file writes static size_t writeBufIndex; - char* const writeBuf = (char *)writeBufStorage; + char* const writeBuf = reinterpret_cast<char *>(writeBufStorage); if (uploadedBytes == 0) { @@ -636,7 +636,7 @@ void Webserver::HttpInterpreter::DoFastUpload() while (len != 0) { - size_t lengthToCopy = min<size_t>(writeBufLength - writeBufIndex, len); + const size_t lengthToCopy = min<size_t>(writeBufLength - writeBufIndex, len); memcpy(writeBuf + writeBufIndex, buffer, lengthToCopy); writeBufIndex += lengthToCopy; uploadedBytes += lengthToCopy; @@ -644,7 +644,7 @@ void Webserver::HttpInterpreter::DoFastUpload() len -= lengthToCopy; if (writeBufIndex == writeBufLength || uploadedBytes >= postFileLength) { - bool success = fileBeingUploaded.Write(writeBuf, writeBufIndex); + const bool success = fileBeingUploaded.Write(writeBuf, writeBufIndex); writeBufIndex = 0; if (!success) { @@ -923,7 +923,7 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command) // Check special cases of deferred requests (rr_fileinfo) and rejected messages NetworkTransaction *transaction = webserver->currentTransaction; - if (transaction->GetStatus() == deferred || transaction->GetStatus() == sending) + if (transaction->GetStatus() == TransactionStatus::deferred || transaction->GetStatus() == TransactionStatus::sending) { OutputBuffer::Release(jsonResponse); return; @@ -2638,14 +2638,14 @@ bool Webserver::TelnetInterpreter::CanParseData() { // Is this an acquired transaction using which we can send the G-code reply? TransactionStatus status = webserver->currentTransaction->GetStatus(); - if (status == acquired) + if (status == TransactionStatus::acquired) { SendGCodeReply(); return false; } // Is this connection still live? Check that for deferred requests - if (status == deferred && !webserver->currentTransaction->IsConnected()) + if (status == TransactionStatus::deferred && !webserver->currentTransaction->IsConnected()) { webserver->currentTransaction->Discard(); return false; |