diff options
author | David Crocker <dcrocker@eschertech.com> | 2018-02-12 21:08:19 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2018-02-12 21:08:19 +0300 |
commit | 99c2896a3e64ca76d67dda59b61ca9a8b5c6856a (patch) | |
tree | b7f4d70a50b3167dac04c6a5d778918448982a54 /src | |
parent | 5fa6a17b4678b54c17dff37b8717cfac15446c7c (diff) |
Combined DuetWiFi and DuetEthernet builds
Diffstat (limited to 'src')
58 files changed, 238 insertions, 14165 deletions
diff --git a/src/Duet/Network.cpp b/src/Duet/Network.cpp index a0b7eaf6..7d20cedb 100644 --- a/src/Duet/Network.cpp +++ b/src/Duet/Network.cpp @@ -279,6 +279,7 @@ void Network::Init() } strcpy(hostname, DEFAULT_HOSTNAME); + memcpy(macAddress, platform.GetDefaultMacAddress(), sizeof(macAddress)); webserver = new Webserver(&platform, this); webserver->Init(); @@ -817,6 +818,14 @@ void Network::SetHostname(const char *name) } } +void Network::SetMacAddress(unsigned int interface, const uint8_t mac[]) +{ + for (size_t i = 0; i < 6; i++) + { + macAddress[i] = mac[i]; + } +} + GCodeResult Network::EnableInterface(unsigned int interface, int mode, const StringRef& ssid, const StringRef& reply) { if (mode != 0) @@ -861,7 +870,7 @@ void Network::Start() if (state == NotStarted) { // Allow the MAC address to be set only before LwIP is started... - ethernet_configure_interface(platform.MACAddress(), hostname); + ethernet_configure_interface(macAddress, hostname); init_ethernet(); netbios_init(); state = NetworkInactive; diff --git a/src/Duet/Network.h b/src/Duet/Network.h index cf0f5d6d..5c817943 100644 --- a/src/Duet/Network.h +++ b/src/Duet/Network.h @@ -75,6 +75,8 @@ public: const uint8_t *GetIPAddress() const; void SetEthernetIPAddress(const uint8_t ipAddress[], const uint8_t netmask[], const uint8_t gateway[]); void SetHostname(const char *name); + void SetMacAddress(unsigned int interface, const uint8_t mac[]); + const uint8_t *GetMacAddress(unsigned int interface) const { return macAddress; } bool IsWiFiInterface(unsigned int interface) const { return false; } GCodeResult EnableInterface(unsigned int interface, int mode, const StringRef& ssid, const StringRef& reply); // enable or disable the network @@ -146,6 +148,7 @@ private: bool activated; volatile bool resetCallback; char hostname[16]; // Limit DHCP hostname to 15 characters + terminating 0 + uint8_t macAddress[6]; ConnectionState * volatile dataCs; ConnectionState * volatile ftpCs; diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h index 6797d675..1975d530 100644 --- a/src/DuetNG/Pins_DuetNG.h +++ b/src/DuetNG/Pins_DuetNG.h @@ -1,36 +1,17 @@ #ifndef PINS_DUETNG_H__ #define PINS_DUETNG_H__ -#if defined(DUET_WIFI) - -# define FIRMWARE_NAME "RepRapFirmware for Duet WiFi" +# define FIRMWARE_NAME "RepRapFirmware for Duet WiFi and Duet Ethernet" # define DEFAULT_BOARD_TYPE BoardType::DuetWiFi_10 -constexpr size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manual upload to WiFi module +constexpr size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manual upload to WiFi module (module 2 is now unused) # 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" -constexpr size_t NumFirmwareUpdateModules = 1; // 1 module - -#else -# error Firmware name not defined -#endif // Features definition #define HAS_LWIP_NETWORKING 0 -#if defined(DUET_ETHERNET) -# define HAS_WIFI_NETWORKING 0 -# define HAS_W5500_NETWORKING 1 -#else # define HAS_WIFI_NETWORKING 1 -# define HAS_W5500_NETWORKING 0 -#endif +# define HAS_W5500_NETWORKING 1 #define HAS_CPU_TEMP_SENSOR 1 #define HAS_HIGH_SPEED_SD 1 @@ -192,23 +173,19 @@ constexpr int HighestLogicalPin = 135; // highest logical pin number on constexpr uint32_t IAP_FLASH_START = 0x00470000; constexpr uint32_t IAP_FLASH_END = 0x0047FFFF; // we allow a full 64K on the SAM4 -#if defined(DUET_WIFI) - -// Duet pin numbers to control the WiFi interface +// Duet pin numbers to control the WiFi interface on the Duet WiFi constexpr Pin EspResetPin = 100; // Low on this in holds the WiFi module in reset (ESP_RESET) constexpr Pin EspEnablePin = 101; // High to enable the WiFi module, low to power it down (ESP_CH_PD) -constexpr Pin EspTransferRequestPin = 95; // Input from the WiFi module indicating that it wants to transfer data (ESP GPIO0) +constexpr Pin EspDataReadyPin = 95; // Input from the WiFi module indicating that it wants to transfer data (ESP GPIO0) constexpr Pin SamTfrReadyPin = 94; // Output from the SAM to the WiFi module indicating we can accept a data transfer (ESP GPIO4 via 7474) constexpr Pin SamCsPin = 11; // SPI NPCS pin, input from WiFi module -#elif defined(DUET_ETHERNET) - -// Duet pin numbers to control the W5500 interface +// Duet pin numbers to control the W5500 interface on the Duet Ethernet constexpr Pin W5500ResetPin = 100; // Low on this in holds the W5500 module in reset (ESP_RESET) +constexpr Pin W5500InterruptPin = 95; // W5500 interrupt output, active low +constexpr Pin W5500ModuleSensePin = 5; // URXD1, tied to ground on the Ethernet module constexpr Pin W5500SsPin = 11; // SPI NPCS pin, input from W5500 module -#endif - // Timer allocation (no network timer on DuetNG) // TC0 channel 0 is used for FAN2 // TC0 channel 1 is currently unused (may use it for a heater or a fan) diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 18e8ed82..3481fbbc 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -2540,24 +2540,27 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) break; case 540: // Set/report MAC address - if (gb.Seen('P')) { - uint8_t mac[6]; - if (gb.GetMacAddress(mac)) + const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); + if (gb.Seen('P')) { - platform.SetMACAddress(mac); + uint8_t mac[6]; + if (gb.GetMacAddress(mac)) + { + reprap.GetNetwork().SetMacAddress(interface, mac); + } + else + { + reply.copy("Bad MAC address"); + result = GCodeResult::error; + } } else { - reply.copy("Bad MAC address"); - result = GCodeResult::error; + const uint8_t * const mac = reprap.GetNetwork().GetMacAddress(interface); + reply.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } } - else - { - const uint8_t *mac = platform.MACAddress(); - reply.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - } break; case 550: // Set/report machine name diff --git a/src/Network2/ESP8266/Network.cpp b/src/Network2/ESP8266/Network.cpp deleted file mode 100644 index ea57fd40..00000000 --- a/src/Network2/ESP8266/Network.cpp +++ /dev/null @@ -1,1692 +0,0 @@ -/**************************************************************************************************** - - RepRapFirmware network comms to ESP8266-based device - - ****************************************************************************************************/ - -#include "Network.h" -#include "ESP8266/WifiFirmwareUploader.h" -#include "Platform.h" -#include "GCodes/GCodeBuffer.h" -#include "RepRap.h" -#include "HttpResponder.h" -#include "FtpResponder.h" -#include "TelnetResponder.h" -#include "Libraries/General/IP4String.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 1 // use general DMA controller - -#if USE_PDC -#include "pdc/pdc.h" -#endif - -#if USE_DMAC -#include "dmac/dmac.h" -#endif - -#include "matrix/matrix.h" - -const uint32_t WifiResponseTimeoutMillis = 200; -const uint32_t WiFiWaitReadyMillis = 100; -const uint32_t WiFiStartupMillis = 300; -const uint32_t WiFiStableMillis = 100; - -const unsigned int MaxHttpConnections = 4; - -const Port DefaultPortNumbers[NumProtocols] = { DefaultHttpPort, DefaultFtpPort, DefaultTelnetPort }; -const char * const ProtocolNames[NumProtocols] = { "HTTP", "FTP", "TELNET" }; - -// Forward declarations of static functions -static void spi_dma_disable(); -static bool spi_dma_check_rx_complete(); - -struct MessageBufferOut -{ - MessageHeaderSamToEsp hdr; - uint8_t data[MaxDataLength]; // data to send -}; - -struct MessageBufferIn -{ - MessageHeaderEspToSam hdr; - uint8_t data[MaxDataLength]; // data to send -}; - -static MessageBufferOut bufferOut; -static MessageBufferIn bufferIn; -static volatile bool transferPending = false; - -#if 0 -static void debugPrintBuffer(const char *msg, void *buf, size_t dataLength) -{ - const size_t MaxDataToPrint = 20; - const uint8_t * const data = reinterpret_cast<const uint8_t *>(buf); - debugPrintf("%s %02x %02x %02x %02x %04x %04x %08x", - msg, - data[0], data[1], data[2], data[3], - *reinterpret_cast<const uint16_t*>(data + 4), *reinterpret_cast<const uint16_t*>(data + 6), - *reinterpret_cast<const uint32_t*>(data + 8)); - if (dataLength != 0) - { - debugPrintf(" "); - for (size_t i = 0; i < min<size_t>(dataLength, MaxDataToPrint); ++i) - { - debugPrintf("%02x", data[i + 12]); - } - if (dataLength > MaxDataToPrint) - { - debugPrintf("..."); - } - } - debugPrintf("\n"); -} -#endif - -static void EspTransferRequestIsr(CallbackParameter) -{ - reprap.GetNetwork().EspRequestsTransfer(); -} - -static inline void EnableEspInterrupt() -{ - attachInterrupt(EspTransferRequestPin, EspTransferRequestIsr, RISING, nullptr); -} - -static inline void DisableEspInterrupt() -{ - detachInterrupt(EspTransferRequestPin); -} - -/*-----------------------------------------------------------------------------------*/ -// WiFi interface class - -Network::Network(Platform& p) : platform(p), nextResponderToPoll(nullptr), uploader(nullptr), currentSocket(0), ftpDataPort(0), - state(NetworkState::disabled), requestedMode(WiFiState::disabled), currentMode(WiFiState::disabled), activated(false), - espStatusChanged(false), spiTxUnderruns(0), spiRxOverruns(0), serialRunning(false) -{ - for (size_t i = 0; i < NumProtocols; ++i) - { - portNumbers[i] = DefaultPortNumbers[i]; - protocolEnabled[i] = (i == HttpProtocol); - } - - // Create the responders - responders = telnetResponder = new TelnetResponder(nullptr); - responders = ftpResponder = new FtpResponder(responders); - for (unsigned int i = 0; i < NumHttpResponders; ++i) - { - responders = new HttpResponder(responders); - } - - strcpy(actualSsid, "(unknown)"); - strcpy(wiFiServerVersion, "(unknown)"); -} - -void Network::Init() -{ - // Make sure the ESP8266 is held in the reset state - ResetWiFi(); - longWait = lastTickMillis = millis(); - - NetworkBuffer::AllocateBuffers(NetworkBufferCount); - - SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway); - strcpy(hostname, HOSTNAME); - - for (size_t i = 0; i < NumTcpSockets; ++i) - { - sockets[i].Init(i); - } - - uploader = new WifiFirmwareUploader(Serial1); - currentSocket = 0; -} - -void Network::EnableProtocol(int protocol, int port, int secure, const StringRef& reply) -{ - if (secure != 0 && secure != -1) - { - reply.copy("Error: this firmware does not support TLS"); - } - else if (protocol >= 0 && protocol < (int)NumProtocols) - { - const Port portToUse = (port < 0) ? DefaultPortNumbers[protocol] : port; - if (portToUse != portNumbers[protocol] && state == NetworkState::active) - { - // We need to shut down and restart the protocol if it is active because the port number has changed - ShutdownProtocol(protocol); - protocolEnabled[protocol] = false; - } - portNumbers[protocol] = portToUse; - if (!protocolEnabled[protocol]) - { - protocolEnabled[protocol] = true; - if (state == NetworkState::active) - { - StartProtocol(protocol); - // mDNS announcement is done by the WiFi Server firmware - } - } - ReportOneProtocol(protocol, reply); - } - else - { - reply.copy("Invalid protocol parameter"); - } -} - -void Network::DisableProtocol(int protocol, const StringRef& reply) -{ - if (protocol >= 0 && protocol < (int)NumProtocols) - { - if (state == NetworkState::active) - { - ShutdownProtocol(protocol); - } - protocolEnabled[protocol] = false; - ReportOneProtocol(protocol, reply); - } - else - { - reply.copy("Invalid protocol parameter"); - } -} - -void Network::StartProtocol(Protocol protocol) -{ - switch(protocol) - { - case HttpProtocol: - SendListenCommand(portNumbers[protocol], protocol, MaxHttpConnections); - break; - - case FtpProtocol: - SendListenCommand(portNumbers[protocol], protocol, 1); - break; - - case TelnetProtocol: - SendListenCommand(portNumbers[protocol], protocol, 1); - break; - - default: - break; - } -} - -void Network::ShutdownProtocol(Protocol protocol) -{ - for (NetworkResponder* r = responders; r != nullptr; r = r->GetNext()) - { - r->Terminate(protocol); - } - switch(protocol) - { - case HttpProtocol: - StopListening(portNumbers[protocol]); - TerminateSockets(portNumbers[protocol]); - break; - - case FtpProtocol: - StopListening(portNumbers[protocol]); - TerminateSockets(portNumbers[protocol]); - if (ftpDataPort != 0) - { - StopListening(ftpDataPort); - TerminateSockets(ftpDataPort); - } - break; - - case TelnetProtocol: - StopListening(portNumbers[protocol]); - TerminateSockets(portNumbers[protocol]); - break; - - default: - break; - } -} - -// Report the protocols and ports in use -void Network::ReportProtocols(const StringRef& reply) const -{ - reply.Clear(); - for (size_t i = 0; i < NumProtocols; ++i) - { - if (i != 0) - { - reply.cat('\n'); - } - ReportOneProtocol(i, reply); - } -} - -void Network::ReportOneProtocol(Protocol protocol, const StringRef& reply) const -{ - if (protocolEnabled[protocol]) - { - reply.catf("%s is enabled on port %u", ProtocolNames[protocol], portNumbers[protocol]); - } - else - { - reply.catf("%s is disabled", ProtocolNames[protocol]); - } -} - -// This is called at the end of config.g processing. -// Start the network if it was enabled -void Network::Activate() -{ - if (!activated) - { - activated = true; - if (requestedMode != WiFiState::disabled) - { - Start(); - } - else - { - platform.Message(UsbMessage, "Network disabled.\n"); - } - } -} - -void Network::Exit() -{ - Stop(); -} - -// Get the network state into the reply buffer, returning true if there is some sort of error -bool Network::GetNetworkState(const StringRef& reply) -{ - switch (state) - { - case NetworkState::disabled: - reply.copy("WiFi module is disabled"); - break; - case NetworkState::starting1: - case NetworkState::starting2: - reply.copy("WiFi module is being started"); - break; - case NetworkState::changingMode: - reply.copy("WiFi module is changing mode"); - break; - case NetworkState::active: - reply.copy("WiFi module is "); - reply.cat(TranslateWiFiState(currentMode)); - if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint) - { - reply.catf("%s, IP address %s", actualSsid, IP4String(ipAddress).c_str()); - } - break; - default: - reply.copy("Unknown network state"); - return true; - break; - } - return false; -} - -// Start up the ESP. We assume it is not already started. -// ESP8266 boot modes: -// GPIO0 GPIO2 GPIO15 -// 0 1 0 Firmware download from UART -// 1 1 0 Normal boot from flash memory -// 0 0 1 SD card boot (not used on Duet) -void Network::Start() -{ - // The ESP8266 is held in a reset state by a pulldown resistor until we enable it. - // Make sure the ESP8266 is in the reset state - pinMode(EspResetPin, OUTPUT_LOW); - - // Take the ESP8266 out of power down - pinMode(EspEnablePin, OUTPUT_HIGH); - - // Set up our transfer request pin (GPIO4) as an output and set it low - pinMode(SamTfrReadyPin, OUTPUT_LOW); - - // Set up our data ready pin (ESP GPIO0) as an output and set it high ready to boot the ESP from flash - pinMode(EspTransferRequestPin, OUTPUT_HIGH); - - // GPIO2 also needs to be high to boot. It's connected to MISO on the SAM, so set the pullup resistor on that pin - pinMode(APIN_SPI_MISO, INPUT_PULLUP); - - // Set our CS input (ESP GPIO15) low ready for booting the ESP. This also clears the transfer ready latch. - pinMode(SamCsPin, OUTPUT_LOW); - - // Make sure it has time to reset - no idea how long it needs, but 20ms should be plenty - delay(50); - - // Release the reset on the ESP8266 - StartWiFi(); - - // Give it time to sample GPIO0 and GPIO15 - // GPIO0 has to be held high for sufficient time: - // - 10ms is not enough - // - 18ms after reset is released, an oscillating signal appears on GPIO0 for 55ms - // - so 18ms is probably long enough. Use 50ms for safety. - delay(50); - - // Relinquish control of our CS pin so that the ESP can take it over - pinMode(SamCsPin, INPUT); - - // Set the data request pin to be an input - pinMode(EspTransferRequestPin, INPUT_PULLUP); - - // The ESP takes about 300ms before it starts talking to us, so don't wait for it here, do that in Spin() - spiTxUnderruns = spiRxOverruns = 0; - reconnectCount = 0; - transferAlreadyPendingCount = readyTimeoutCount = responseTimeoutCount = 0; - - lastTickMillis = millis(); - state = NetworkState::starting1; -} - -// Stop the ESP -void Network::Stop() -{ - if (state != NetworkState::disabled) - { - digitalWrite(SamTfrReadyPin, LOW); // tell the ESP we can't receive - digitalWrite(EspResetPin, LOW); // put the ESP back into reset - DisableEspInterrupt(); // ignore IRQs from the transfer request pin - - NVIC_DisableIRQ(SPI_IRQn); - spi_disable(SPI); - spi_dma_check_rx_complete(); - spi_dma_disable(); - - state = NetworkState::disabled; - currentMode = WiFiState::disabled; - } -} - -void Network::Spin(bool full) -{ - if (full) - { - // Main state machine. - switch (state) - { - case NetworkState::starting1: - { - // The ESP toggles CS before it has finished starting up, so don't look at the CS signal too soon - const uint32_t now = millis(); - if (now - lastTickMillis >= WiFiStartupMillis) - { - lastTickMillis = now; - state = NetworkState::starting2; - } - } - break; - - case NetworkState::starting2: - { - // See if the ESP8266 has kept its pins at their stable values for long enough - const uint32_t now = millis(); - if (digitalRead(SamCsPin) && digitalRead(EspTransferRequestPin) && !digitalRead(APIN_SPI_SCK)) - { - if (now - lastTickMillis >= WiFiStableMillis) - { - // Setup the SPI controller in slave mode and assign the CS pin to it - platform.Message(NetworkInfoMessage, "WiFi module started\n"); - SetupSpi(); // set up the SPI subsystem - - // Read the status to get the WiFi server version - Receiver<NetworkStatusResponse> status; - const int32_t rc = SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status); - if (rc > 0) - { - SafeStrncpy(wiFiServerVersion, status.Value().versionText, ARRAY_SIZE(wiFiServerVersion)); - - // Set the hostname before anything else is done - if (SendCommand(NetworkCommand::networkSetHostName, 0, 0, hostname, HostNameLength, nullptr, 0) != ResponseEmpty) - { - reprap.GetPlatform().Message(NetworkInfoMessage, "Error: Could not set WiFi hostname\n"); - } - - state = NetworkState::active; - espStatusChanged = true; // make sure we fetch the current state and enable the ESP interrupt - } - else - { - // Something went wrong, maybe a bad firmware image was flashed - // Disable the WiFi chip again in this case - platform.MessageF(NetworkInfoMessage, "Error: Failed to initialise WiFi module, code %" PRIi32 "\n", rc); - Stop(); - } - } - } - else - { - lastTickMillis = now; - } - } - break; - - case NetworkState::disabled: - uploader->Spin(); - break; - - case NetworkState::active: - if (espStatusChanged && digitalRead(EspTransferRequestPin)) - { - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("ESP reported status change\n"); - } - GetNewStatus(); - } - else if ( currentMode != requestedMode - && currentMode != WiFiState::connecting - && currentMode != WiFiState::reconnecting - && currentMode != WiFiState::autoReconnecting - ) - { - // Tell the wifi module to change mode - int32_t rslt = ResponseUnknownError; - if (currentMode != WiFiState::idle) - { - // We must set WiFi module back to idle before changing to the new state - rslt = SendCommand(NetworkCommand::networkStop, 0, 0, nullptr, 0, nullptr, 0); - } - else if (requestedMode == WiFiState::connected) - { - rslt = SendCommand(NetworkCommand::networkStartClient, 0, 0, requestedSsid, SsidLength, nullptr, 0); - } - else if (requestedMode == WiFiState::runningAsAccessPoint) - { - rslt = SendCommand(NetworkCommand::networkStartAccessPoint, 0, 0, nullptr, 0, nullptr, 0); - } - - if (rslt >= 0) - { - state = NetworkState::changingMode; - } - else - { - Stop(); - platform.MessageF(NetworkInfoMessage, "Failed to change WiFi mode (code %" PRIi32 ")\n", rslt); - } - } - else if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint) - { - // Find the next socket to poll - const size_t startingSocket = currentSocket; - do - { - if (sockets[currentSocket].NeedsPolling()) - { - break; - } - ++currentSocket; - if (currentSocket == NumTcpSockets) - { - currentSocket = 0; - } - } while (currentSocket != startingSocket); - - // Either the current socket needs polling, or no sockets do but we must still poll one of them to get notified of any new connections - sockets[currentSocket].Poll(full); - ++currentSocket; - if (currentSocket == NumTcpSockets) - { - currentSocket = 0; - } - - // Poll the responders - if (full) - { - NetworkResponder *nr = nextResponderToPoll; - bool doneSomething = false; - do - { - if (nr == nullptr) - { - nr = responders; // 'responders' can't be null at this point - } - doneSomething = nr->Spin(); - nr = nr->GetNext(); - } while (!doneSomething && nr != nextResponderToPoll); - nextResponderToPoll = nr; - } - } - break; - - case NetworkState::changingMode: - if (espStatusChanged && digitalRead(EspTransferRequestPin)) - { - GetNewStatus(); - if (currentMode != WiFiState::connecting) - { - requestedMode = currentMode; // don't keep repeating the request if it failed - state = NetworkState::active; - if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint) - { - // Get our IP address, this needs to be correct for FTP to work - Receiver<NetworkStatusResponse> status; - if (SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status) > 0) - { - uint32_t ip = status.Value().ipAddress; - for (size_t i = 0; i < 4; ++i) - { - ipAddress[i] = (uint8_t)(ip & 255); - ip >>= 8; - } - SafeStrncpy(actualSsid, status.Value().ssid, SsidLength); - } - InitSockets(); - reconnectCount = 0; - platform.MessageF(NetworkInfoMessage, "Wifi module is %s%s, IP address %s\n", - TranslateWiFiState(currentMode), - actualSsid, - IP4String(ipAddress).c_str()); - } - else - { - platform.MessageF(NetworkInfoMessage, "Wifi module is %s\n", TranslateWiFiState(currentMode)); - } - } - } - break; - - default: - break; - } - } - - // Check for debug info received from the WiFi module - if (serialRunning) - { - while (!debugPrintPending && Serial1.available() != 0) - { - const char c = (char)Serial1.read(); - if (c == '\n') - { - debugPrintPending = true; - } - else if (c != '\r') - { - const size_t len = debugMessageBuffer.cat(c); - if (len == debugMessageBuffer.MaxLength()) - { - debugPrintPending = true; - } - } - } - } - - if (full) - { - // Check for debug info received from the WiFi module - if (debugPrintPending) - { - if (reprap.Debug(moduleWiFi)) - { - debugPrintf("WiFi: %s\n", debugMessageBuffer.Pointer()); - } - debugMessageBuffer.Clear(); - debugPrintPending = false; - } - - platform.ClassReport(longWait); - } -} - -// Translate a ESP8266 reset reason to text -const char* Network::TranslateEspResetReason(uint32_t reason) -{ - // Mapping from known ESP reset codes to reasons - static const char * const resetReasonTexts[] = - { - "Power on", - "Hardware watchdog", - "Exception", - "Software watchdog", - "Software restart", - "Deep-sleep wakeup", - "Turned on by main processor" - }; - - return (reason < sizeof(resetReasonTexts)/sizeof(resetReasonTexts[0])) - ? resetReasonTexts[reason] - : "Unknown"; -} - -const char* Network::TranslateNetworkState() const -{ - switch (state) - { - case NetworkState::disabled: return "disabled"; - case NetworkState::starting1: - case NetworkState::starting2: return "starting"; - case NetworkState::active: return "running"; - case NetworkState::changingMode: return "changing mode"; - default: return "unknown"; - } -} - -void Network::Diagnostics(MessageType mtype) -{ - platform.MessageF(mtype, "=== Network ===\nNetwork state is %s\n", TranslateNetworkState()); - platform.MessageF(mtype, "WiFi module is %s\n", TranslateWiFiState(currentMode)); - platform.MessageF(mtype, "Failed messages: pending %u, notready %u, noresp %u\n", transferAlreadyPendingCount, readyTimeoutCount, responseTimeoutCount); - -#if 0 - // The underrun/overrun counters don't work at present - platform.MessageF(mtype, "SPI underruns %u, overruns %u\n", spiTxUnderruns, spiRxOverruns); -#endif - - if (state != NetworkState::disabled && state != NetworkState::starting1 && state != NetworkState::starting2) - { - Receiver<NetworkStatusResponse> status; - if (SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status) > 0) - { - NetworkStatusResponse& r = status.Value(); - r.versionText[ARRAY_UPB(r.versionText)] = 0; - platform.MessageF(mtype, "WiFi firmware version %s\n", r.versionText); - platform.MessageF(mtype, "WiFi MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", - r.macAddress[0], r.macAddress[1], r.macAddress[2], r.macAddress[3], r.macAddress[4], r.macAddress[5]); - platform.MessageF(mtype, "WiFi Vcc %.2f, reset reason %s\n", (double)((float)r.vcc/1024), TranslateEspResetReason(r.resetReason)); - platform.MessageF(mtype, "WiFi flash size %" PRIu32 ", free heap %" PRIu32 "\n", r.flashSize, r.freeHeap); - - if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint) - { - platform.MessageF(mtype, "WiFi IP address %s\n", IP4String(r.ipAddress).c_str()); - } - - if (currentMode == WiFiState::connected) - { - const char* const sleepMode = (r.sleepMode == 1) ? "none" : (r.sleepMode == 2) ? "light" : (r.sleepMode == 3) ? "modem" : "unknown"; - platform.MessageF(mtype, "WiFi signal strength %ddBm, reconnections %u, sleep mode %s\n", (int)r.rssi, reconnectCount, sleepMode); - } - else if (currentMode == WiFiState::runningAsAccessPoint) - { - platform.MessageF(mtype, "Connected clients %u\n", (unsigned int)r.numClients); - } - // status, ssid and hostName not displayed - - // Print LwIP stats and other values over the ESP's UART line - if (SendCommand(NetworkCommand::diagnostics, 0, 0, nullptr, 0, nullptr, 0) != ResponseEmpty) - { - platform.Message(mtype, "Failed to request ESP stats\n"); - } - } - else - { - platform.Message(mtype, "Failed to get WiFi status\n"); - } - } - HttpResponder::CommonDiagnostics(mtype); - platform.Message(mtype, "Socket states: "); - for (size_t i = 0; i < NumTcpSockets; i++) - { - platform.MessageF(mtype, " %d", sockets[i].State()); - } - platform.Message(mtype, "\nResponder states:"); - for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) - { - r->Diagnostics(mtype); - } - platform.Message(mtype, "\n"); -} - -// Enable or disable the network -void Network::Enable(int mode, const StringRef& ssid, const StringRef& reply) -{ - // Translate enable mode to desired WiFi mode - const WiFiState modeRequested = (mode == 0) ? WiFiState::idle - : (mode == 1) ? WiFiState::connected - : (mode == 2) ? WiFiState::runningAsAccessPoint - : WiFiState::disabled; - if (modeRequested == WiFiState::connected) - { - memset(requestedSsid, 0, sizeof(requestedSsid)); - SafeStrncpy(requestedSsid, ssid.Pointer(), ARRAY_SIZE(requestedSsid)); - } - - if (activated) - { - if (modeRequested == WiFiState::disabled) - { - // Shut down WiFi module completely - requestedMode = modeRequested; - if (state != NetworkState::disabled) - { - Stop(); - platform.Message(GenericMessage, "WiFi module stopped\n"); - } - } - else - { - if (state == NetworkState::disabled) - { - requestedMode = modeRequested; - Start(); - } - else if (modeRequested == currentMode || (modeRequested == WiFiState::connected && currentMode == WiFiState::connecting)) - { - // Nothing to do, but make sure the requested mode is correct - requestedMode = modeRequested; - } - else if (currentMode != WiFiState::idle && modeRequested != WiFiState::idle) - { - reply.copy("Turn off the current WiFi mode before selecting a new one"); - } - else - { - requestedMode = modeRequested; - } - } - } - else - { - requestedMode = modeRequested; - } -} - -int Network::EnableState() const -{ - return (requestedMode == WiFiState::idle) ? 0 - : (requestedMode == WiFiState::connected) ? 1 - : (requestedMode == WiFiState::runningAsAccessPoint) ? 2 - : -1; -} - -GCodeResult Network::HandleWiFiCode(int mcode, GCodeBuffer &gb, const StringRef& reply, OutputBuffer*& longReply) -{ - switch (mcode) - { - case 587: // Add WiFi network or list remembered networks - if (gb.Seen('S')) - { - WirelessConfigurationData config; - memset(&config, 0, sizeof(config)); - String<ARRAY_SIZE(config.ssid)> ssid; - bool ok = gb.GetQuotedString(ssid.GetRef()); - if (ok) - { - SafeStrncpy(config.ssid, ssid.c_str(), ARRAY_SIZE(config.ssid)); - String<ARRAY_SIZE(config.password)> password; - ok = gb.Seen('P') && gb.GetQuotedString(password.GetRef()); - if (ok) - { - if (password.strlen() < 8 && password.strlen() != 0) // WPA2 passwords must be at least 8 characters - { - reply.copy("WiFi password must be at least 8 characters"); - return GCodeResult::error; - } - SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); - } - } - if (ok && gb.Seen('I')) - { - gb.GetIPAddress(config.ip); - } - if (ok && gb.Seen('J')) - { - ok = gb.GetIPAddress(config.gateway); - } - if (ok && gb.Seen('K')) - { - ok = gb.GetIPAddress(config.netmask); - } - if (ok) - { - const int32_t rslt = SendCommand(NetworkCommand::networkAddSsid, 0, 0, &config, sizeof(config), nullptr, 0); - if (rslt == ResponseEmpty) - { - return GCodeResult::ok; - } - else - { - reply.copy("Failed to add SSID to remembered list"); - } - } - else - { - reply.copy("Bad or missing parameter"); - } - } - else - { - // List remembered networks - const size_t declaredBufferLength = (MaxRememberedNetworks + 1) * ReducedWirelessConfigurationDataSize; // enough for all the remembered SSID data - uint32_t buffer[NumDwords(declaredBufferLength)]; - const int32_t rslt = SendCommand(NetworkCommand::networkRetrieveSsidData, 0, 0, nullptr, 0, buffer, declaredBufferLength); - if (rslt >= 0) - { - size_t offset = ReducedWirelessConfigurationDataSize; // skip own SSID details - while (offset + ReducedWirelessConfigurationDataSize <= (size_t)rslt) - { - WirelessConfigurationData* const wp = reinterpret_cast<WirelessConfigurationData *>(reinterpret_cast<char*>(buffer) + offset); - if (wp->ssid[0] != 0) - { - if (longReply == nullptr) - { - if (!OutputBuffer::Allocate(longReply)) - { - return GCodeResult::notFinished; // try again later - } - longReply->copy("Remembered networks:"); - } - wp->ssid[ARRAY_UPB(wp->ssid)] = 0; - longReply->catf("\n%s IP=%s GW=%s NM=%s", wp->ssid, IP4String(wp->ip).c_str(), IP4String(wp->gateway).c_str(), IP4String(wp->netmask).c_str()); - } - offset += ReducedWirelessConfigurationDataSize; - } - - if (longReply == nullptr) - { - reply.copy("No remembered networks"); - } - return GCodeResult::ok; - } - - reply.copy("Failed to retrieve network list"); - } - return GCodeResult::error; - - case 588: // Forget WiFi network - if (gb.Seen('S')) - { - String<SsidLength> ssidText; - if (gb.GetQuotedString(ssidText.GetRef())) - { - if (strcmp(ssidText.c_str(), "*") == 0) - { - const int32_t rslt = SendCommand(NetworkCommand::networkFactoryReset, 0, 0, nullptr, 0, nullptr, 0); - if (rslt == ResponseEmpty) - { - return GCodeResult::ok; - } - - reply.copy("Failed to reset the WiFi module to factory settings"); - return GCodeResult::error; - } - - uint32_t ssid32[NumDwords(SsidLength)]; // need a dword-aligned buffer for SendCommand - memcpy(ssid32, ssidText.c_str(), SsidLength); - const int32_t rslt = SendCommand(NetworkCommand::networkDeleteSsid, 0, 0, ssid32, SsidLength, nullptr, 0); - if (rslt == ResponseEmpty) - { - return GCodeResult::ok; - } - - reply.copy("Failed to remove SSID from remembered list"); - return GCodeResult::error; - } - } - - reply.copy("Bad or missing parameter"); - return GCodeResult::error; - - case 589: // Configure access point - if (gb.Seen('S')) - { - // Configure access point parameters - WirelessConfigurationData config; - memset(&config, 0, sizeof(config)); - String<SsidLength> ssid; - bool ok = gb.GetQuotedString(ssid.GetRef()); - if (ok) - { - if (strcmp(ssid.c_str(), "*") == 0) - { - // Delete the access point details - memset(&config, 0xFF, sizeof(config)); - } - else - { - SafeStrncpy(config.ssid, ssid.c_str(), ARRAY_SIZE(config.ssid)); - String<ARRAY_SIZE(config.password)> password; - ok = gb.Seen('P') && gb.GetQuotedString(password.GetRef()); - if (ok) - { - SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); - if (gb.Seen('I')) - { - ok = gb.GetIPAddress(config.ip); - config.channel = (gb.Seen('C')) ? gb.GetIValue() : 0; - } - else - { - ok = false; - } - } - } - } - if (ok) - { - const int32_t rslt = SendCommand(NetworkCommand::networkConfigureAccessPoint, 0, 0, &config, sizeof(config), nullptr, 0); - if (rslt == ResponseEmpty) - { - return GCodeResult::ok; - } - - reply.copy("Failed to configure access point parameters"); - } - else - { - reply.copy("Bad or missing parameter"); - } - } - else - { - // Report access point parameters - uint32_t buffer[NumDwords(ReducedWirelessConfigurationDataSize)]; - const int32_t rslt = SendCommand(NetworkCommand::networkRetrieveSsidData, 0, 0, nullptr, 0, buffer, ReducedWirelessConfigurationDataSize); - if (rslt >= 0) - { - WirelessConfigurationData* const wp = reinterpret_cast<WirelessConfigurationData *>(buffer); - if (wp->ssid[0] == 0) - { - reply.copy("Own SSID not configured"); - } - else - { - wp->ssid[ARRAY_UPB(wp->ssid)] = 0; - reply.printf("Own SSID: %s IP=%s GW=%s NM=%s", wp->ssid, IP4String(wp->ip).c_str(), IP4String(wp->gateway).c_str(), IP4String(wp->netmask).c_str()); - return GCodeResult::ok; - } - } - else - { - reply.copy("Failed to retrieve own SSID data"); - } - } - return GCodeResult::error; - - default: // should not happen - return GCodeResult::error; - } -} - -// Translate the wifi state to text. -// The 'connected' and 'runningAsAccessPoint' states include a space at the end because the caller is expected to append the access point name. -/*static*/ const char* Network::TranslateWiFiState(WiFiState w) -{ - switch (w) - { - case WiFiState::disabled: return "disabled"; - case WiFiState::idle: return "idle"; - case WiFiState::connecting: return "trying to connect"; - case WiFiState::connected: return "connected to access point "; - case WiFiState::runningAsAccessPoint: return "providing access point "; - case WiFiState::autoReconnecting: return "auto-reconnecting"; - case WiFiState::reconnecting: return "reconnecting"; - default: return "in an unknown state"; - } -} - -void Network::EspRequestsTransfer() -{ - espStatusChanged = true; - DisableEspInterrupt(); // don't allow more interrupts until we have acknowledged this one -} - -void Network::SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]) -{ - memcpy(ipAddress, p_ipAddress, sizeof(ipAddress)); - memcpy(netmask, p_netmask, sizeof(netmask)); - memcpy(gateway, p_gateway, sizeof(gateway)); -} - -// Set the DHCP hostname. Removes all whitespaces and converts the name to lower-case. -void Network::SetHostname(const char *name) -{ - // Filter out illegal characters - size_t i = 0; - while (*name && i < ARRAY_UPB(hostname)) - { - char c = *name++; - if (c >= 'A' && c <= 'Z') - { - c += 'a' - 'A'; - } - - if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '-') || (c == '_')) - { - hostname[i++] = c; - } - } - - if (i != 0) - { - hostname[i] = 0; - } - else - { - strcpy(hostname, HOSTNAME); - } - - // Update the hostname if possible - if (state == NetworkState::active) - { - if (SendCommand(NetworkCommand::networkSetHostName, 0, 0, hostname, HostNameLength, nullptr, 0) != ResponseEmpty) - { - platform.Message(GenericMessage, "Error: Could not set WiFi hostname\n"); - } - } -} - -void Network::InitSockets() -{ - for (size_t i = 0; i < NumProtocols; ++i) - { - if (protocolEnabled[i]) - { - StartProtocol(i); - } - } - currentSocket = 0; -} - -void Network::TerminateSockets() -{ - for (SocketNumber skt = 0; skt < NumTcpSockets; ++skt) - { - sockets[skt].Terminate(); - } -} - -void Network::TerminateSockets(Port port) -{ - for (SocketNumber skt = 0; skt < NumTcpSockets; ++skt) - { - if (sockets[skt].GetLocalPort() == port) - { - sockets[skt].Terminate(); - } - } -} - -// This is called to tell the network which sockets are active -void Network::UpdateSocketStatus(uint16_t connectedSockets, uint16_t otherEndClosedSockets) -{ - for (size_t i = 0; i < NumTcpSockets; ++i) - { - if (((connectedSockets | otherEndClosedSockets) & (1u << i)) != 0) - { - sockets[i].SetNeedsPolling(); - } - } -} - -// Find a responder to process a new connection -bool Network::FindResponder(Socket *skt, Port localPort) -{ - // Get the right protocol - Protocol protocol; - if (localPort == ftpDataPort) - { - protocol = FtpDataProtocol; - } - else - { - bool protocolFound = false; - for (size_t i = 0; i < NumProtocols; ++i) - { - if (protocolEnabled[i] && portNumbers[i] == localPort) - { - protocol = i; - protocolFound = true; - break; - } - } - - if (!protocolFound) - { - // Protocol is disabled - return false; - } - } - - // Try to find a responder to deal with this connection - for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) - { - if (r->Accept(skt, protocol)) - { - return true; - } - } - return false; -} - -// Open the FTP data port -void Network::OpenDataPort(Port port) -{ - ftpDataPort = port; - SendListenCommand(ftpDataPort, FtpDataProtocol, 1); -} - -// Close FTP data port and purge associated resources -void Network::TerminateDataPort() -{ - if (ftpDataPort != 0) - { - StopListening(ftpDataPort); - for (SocketNumber skt = 0; skt < NumTcpSockets; ++skt) - { - if (sockets[skt].GetLocalPort() == ftpDataPort) - { - sockets[skt].TerminatePolitely(); - } - } - ftpDataPort = 0; - } -} - -void Network::DataPortClosing() -{ - StopListening(ftpDataPort); -} - -void Network::HandleHttpGCodeReply(const char *msg) -{ - HttpResponder::HandleGCodeReply(msg); -} - -void Network::HandleTelnetGCodeReply(const char *msg) -{ - telnetResponder->HandleGCodeReply(msg); -} - -void Network::HandleHttpGCodeReply(OutputBuffer *buf) -{ - HttpResponder::HandleGCodeReply(buf); -} - -void Network::HandleTelnetGCodeReply(OutputBuffer *buf) -{ - telnetResponder->HandleGCodeReply(buf); -} - -uint32_t Network::GetHttpReplySeq() -{ - return HttpResponder::GetReplySeq(); -} - -#if USE_PDC -static Pdc *spi_pdc; -#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; - -#endif - -static inline void spi_rx_dma_enable() -{ -#if USE_PDC - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN); -#endif - -#if USE_DMAC - dmac_channel_enable(DMAC, CONF_SPI_DMAC_RX_CH); -#endif -} - -static inline void spi_tx_dma_enable() -{ -#if USE_PDC - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN); -#endif - -#if USE_DMAC - dmac_channel_enable(DMAC, CONF_SPI_DMAC_TX_CH); -#endif -} - -static inline void spi_rx_dma_disable() -{ -#if USE_PDC - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS); -#endif - -#if USE_DMAC - dmac_channel_disable(DMAC, CONF_SPI_DMAC_RX_CH); -#endif -} - -static inline void spi_tx_dma_disable() -{ -#if USE_PDC - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS); -#endif - -#if USE_DMAC - dmac_channel_disable(DMAC, CONF_SPI_DMAC_TX_CH); -#endif -} - -static void spi_dma_disable() -{ - spi_tx_dma_disable(); - spi_rx_dma_disable(); -} - -static bool spi_dma_check_rx_complete() -{ -#if USE_PDC - return true; -#endif - -#if USE_DMAC - const 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; -#endif -} - -static void spi_tx_dma_setup(const void *buf, uint32_t transferLength) -{ -#if USE_PDC - pdc_packet_t pdc_spi_packet; - pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); - pdc_spi_packet.ul_size = transferLength; - pdc_tx_init(spi_pdc, &pdc_spi_packet, NULL); -#endif - -#if USE_DMAC - 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, transferLength | 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); -#endif -} - -static void spi_rx_dma_setup(const void *buf, uint32_t transferLength) -{ -#if USE_PDC - pdc_packet_t pdc_spi_packet; - pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); - pdc_spi_packet.ul_size = transferLength; - pdc_rx_init(spi_pdc, &pdc_spi_packet, NULL); -#endif - -#if USE_DMAC - 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, transferLength | 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 -} - -/** - * \brief Set SPI slave transfer. - */ -static void spi_slave_dma_setup(uint32_t dataOutSize, uint32_t dataInSize) -{ -#if USE_PDC - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS); - spi_rx_dma_setup(&bufferIn, dataInSize + sizeof(MessageHeaderEspToSam)); - spi_tx_dma_setup(&bufferOut, dataOutSize + sizeof(MessageHeaderSamToEsp)); - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN); -#endif - -#if USE_DMAC - spi_dma_disable(); - - spi_rx_dma_setup(&bufferIn, dataInSize + sizeof(MessageHeaderEspToSam)); - spi_rx_dma_enable(); - spi_tx_dma_setup(&bufferOut, dataOutSize + sizeof(MessageHeaderSamToEsp)); - spi_tx_dma_enable(); -#endif -} - -// Set up the SPI system -void Network::SetupSpi() -{ -#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]); - ConfigurePin(g_APinDescription[APIN_SPI_SS0]); - - pmc_enable_periph_clk(ID_SPI); - spi_dma_disable(); - spi_reset(SPI); // this clears the transmit and receive registers and puts the SPI into slave mode - -#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)SPI->SPI_SR; // clear any pending interrupt - SPI->SPI_IDR = SPI_IER_NSSR; // disable the interrupt - - NVIC_SetPriority(SPI_IRQn, NvicPrioritySpi); - NVIC_EnableIRQ(SPI_IRQn); -} - -// Send a command to the ESP and get the result -int32_t Network::SendCommand(NetworkCommand cmd, SocketNumber socketNum, uint8_t flags, const void *dataOut, size_t dataOutLength, void* dataIn, size_t dataInLength) -{ - if (state == NetworkState::disabled) - { - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("ResponseNetworkDisabled\n"); - } - return ResponseNetworkDisabled; - } - - if (transferPending) - { - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("ResponseBusy\n"); - } - ++transferAlreadyPendingCount; - return ResponseBusy; - } - - // Wait for the ESP to be ready, with timeout - { - const uint32_t now = millis(); - while (!digitalRead(EspTransferRequestPin)) - { - if (millis() - now > WiFiWaitReadyMillis) - { - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("ResponseBusy\n"); - } - ++readyTimeoutCount; - return ResponseBusy; - } - } - } - - bufferOut.hdr.formatVersion = MyFormatVersion; - bufferOut.hdr.command = cmd; - bufferOut.hdr.socketNumber = socketNum; - bufferOut.hdr.flags = flags; - bufferOut.hdr.param32 = 0; - bufferOut.hdr.dataLength = (uint16_t)dataOutLength; - bufferOut.hdr.dataBufferAvailable = (uint16_t)dataInLength; - if (dataOut != nullptr) - { - memcpy(bufferOut.data, dataOut, dataOutLength); - } - bufferIn.hdr.formatVersion = InvalidFormatVersion; - transferPending = true; - - // DMA may have transferred an extra word to the SPI transmit data register. We need to clear this. - // The only way I can find to do this is to issue a software reset to the SPI system. - // Fortunately, this leaves the SPI system in slave mode. - spi_reset(SPI); - spi_set_bits_per_transfer(SPI, 0, SPI_CSR_BITS_8_BIT); - - // Set up the DMA controller - spi_slave_dma_setup(dataOutLength, dataInLength); - spi_enable(SPI); - - // Enable the end-of transfer interrupt - (void)SPI->SPI_SR; // clear any pending interrupt - SPI->SPI_IER = SPI_IER_NSSR; // enable the NSS rising interrupt - - // Tell the ESP that we are ready to accept data - digitalWrite(SamTfrReadyPin, HIGH); - - // Wait for the DMA complete interrupt, with timeout - { - const uint32_t now = millis(); - while (transferPending || !spi_dma_check_rx_complete()) - { - if (millis() - now > WifiResponseTimeoutMillis) - { - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("ResponseTimeout, pending=%d\n", (int)transferPending); - } - transferPending = false; - spi_dma_disable(); - ++responseTimeoutCount; - return ResponseTimeout; - } - } - } - - // Look at the response - int32_t response; - if (bufferIn.hdr.formatVersion != MyFormatVersion) - { - response = ResponseBadReplyFormatVersion; - } - else - { - if ( (bufferIn.hdr.state == WiFiState::autoReconnecting || bufferIn.hdr.state == WiFiState::reconnecting) - && currentMode != WiFiState::autoReconnecting && currentMode != WiFiState::reconnecting - ) - { - ++reconnectCount; - } - currentMode = bufferIn.hdr.state; - response = bufferIn.hdr.response; - if (response > 0 && dataIn != nullptr) - { - memcpy(dataIn, bufferIn.data, min<size_t>(dataInLength, (size_t)response)); - } - } - - if (response < 0 && reprap.Debug(moduleNetwork)) - { - debugPrintf("Network command %d socket %u returned error %" PRIi32 "\n", (int)cmd, socketNum, response); - } - -#if 0 - //***TEMP debug - if (cmd != NetworkCommand::connGetStatus) - { - debugPrintBuffer("Recv", &bufferIn, (dataIn == nullptr) ? 0 : (size_t)max<int>(0, response)); - } -#endif - - return response; -} - -void Network::SendListenCommand(Port port, Protocol protocol, unsigned int maxConnections) -{ - ListenOrConnectData lcb; - lcb.port = port; - lcb.protocol = protocol; - lcb.remoteIp = AnyIp; - lcb.maxConnections = maxConnections; - SendCommand(NetworkCommand::networkListen, 0, 0, &lcb, sizeof(lcb), nullptr, 0); -} - -// Stop listening on a port -void Network::StopListening(Port port) -{ - SendListenCommand(port, AnyProtocol, 0); -} - -// This is called when ESP is signalling to us that an error occurred or there was a state change -void Network::GetNewStatus() -{ - struct MessageResponse - { - char messageBuffer[100]; - }; - Receiver<MessageResponse> rcvr; - - espStatusChanged = false; - EnableEspInterrupt(); - - const int32_t rslt = SendCommand(NetworkCommand::networkGetLastError, 0, 0, nullptr, 0, rcvr); - rcvr.Value().messageBuffer[ARRAY_UPB(rcvr.Value().messageBuffer)] = 0; - if (rslt < 0) - { - platform.Message(NetworkInfoMessage, "Error retrieving WiFi status message\n"); - } - else if (rslt > 0 && rcvr.Value().messageBuffer[0] != 0) - { - platform.MessageF(NetworkInfoMessage, "WiFi reported error: %s\n", rcvr.Value().messageBuffer); - } -} - -// SPI interrupt handler, called when NSS goes high -void SPI_Handler() -{ - reprap.GetNetwork().SpiInterrupt(); -} - -void Network::SpiInterrupt() -{ - const uint32_t status = SPI->SPI_SR; // read status and clear interrupt - SPI->SPI_IDR = SPI_IER_NSSR; // disable the interrupt - if ((status & SPI_SR_NSSR) != 0) - { -#if USE_PDC - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS); -#endif - -#if USE_DMAC - spi_tx_dma_disable(); - dmac_channel_suspend(DMAC, CONF_SPI_DMAC_RX_CH); // suspend the receive channel, don't disable it because the FIFO needs to empty first -#endif - spi_disable(SPI); - digitalWrite(SamTfrReadyPin, LOW); - if ((status & SPI_SR_OVRES) != 0) - { - ++spiRxOverruns; - } - if ((status & SPI_SR_UNDES) != 0) - { - ++spiTxUnderruns; - } - transferPending = false; - } -} - -// Start the ESP -void Network::StartWiFi() -{ - digitalWrite(EspResetPin, HIGH); - ConfigurePin(g_APinDescription[APINS_UART1]); // connect the pins to UART1 - Serial1.begin(WiFiBaudRate); // initialise the UART, to receive debug info - debugMessageBuffer.Clear(); - serialRunning = true; - debugPrintPending = false; -} - -// Reset the ESP8266 and leave held in reset -void Network::ResetWiFi() -{ - pinMode(EspResetPin, OUTPUT_LOW); // assert ESP8266 /RESET - pinMode(APIN_UART1_TXD, INPUT_PULLUP); // just enable pullups on TxD and RxD pins for now to avoid floating pins - pinMode(APIN_UART1_RXD, INPUT_PULLUP); - currentMode = WiFiState::disabled; - - if (serialRunning) - { - Serial1.end(); - serialRunning = false; - } -} - -// Reset the ESP8266 to take commands from the UART or from external input. The caller must wait for the reset to complete after calling this. -// ESP8266 boot modes: -// GPIO0 GPIO2 GPIO15 -// 0 1 0 Firmware download from UART -// 1 1 0 Normal boot from flash memory -// 0 0 1 SD card boot (not used in on Duet) -void Network::ResetWiFiForUpload(bool external) -{ - if (serialRunning) - { - Serial1.end(); - serialRunning = false; - } - - // Make sure the ESP8266 is in the reset state - pinMode(EspResetPin, OUTPUT_LOW); - - // Take the ESP8266 out of power down - pinMode(EspEnablePin, OUTPUT_HIGH); - - // Set up our transfer request pin (GPIO4) as an output and set it low - pinMode(SamTfrReadyPin, OUTPUT_LOW); - - // Set up our data ready pin (ESP GPIO0) as an output and set it low ready to boot the ESP from UART - pinMode(EspTransferRequestPin, OUTPUT_LOW); - - // GPIO2 also needs to be high to boot up. It's connected to MISO on the SAM, so set the pullup resistor on that pin - pinMode(APIN_SPI_MISO, INPUT_PULLUP); - - // Set our CS input (ESP GPIO15) low ready for booting the ESP. This also clears the transfer ready latch. - pinMode(SamCsPin, OUTPUT_LOW); - - // Make sure it has time to reset - no idea how long it needs, but 50ms should be plenty - delay(50); - - if (external) - { - pinMode(APIN_UART1_TXD, INPUT_PULLUP); // just enable pullups on TxD and RxD pins - pinMode(APIN_UART1_RXD, INPUT_PULLUP); - } - else - { - ConfigurePin(g_APinDescription[APINS_UART1]); // connect the pins to UART1 - } - - // Release the reset on the ESP8266 - digitalWrite(EspResetPin, HIGH); -} - -// End diff --git a/src/Network2/ESP8266/Network.h b/src/Network2/ESP8266/Network.h deleted file mode 100644 index 0639758b..00000000 --- a/src/Network2/ESP8266/Network.h +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************************************** - -RepRapFirmware - Network: RepRapPro Ormerod with Duet controller - -Separated out from Platform.h by dc42 and extended by chrishamm - -****************************************************************************************************/ - -#ifndef NETWORK_H -#define NETWORK_H - -#include "ESP8266/Socket.h" -#include "NetworkDefs.h" -#include "RepRapFirmware.h" -#include "MessageType.h" -#include "MessageFormats.h" -#include "GCodes/GCodeResult.h" - -class NetworkResponder; -class HttpResponder; -class FtpResponder; -class TelnetResponder; -class WifiFirmwareUploader; - -const unsigned int NumHttpResponders = 4; // the number of concurrent HTTP requests we can process - -// Class to allow us to receive some data allowing for some extra bytes being stored by the DMAC -template<class T> class Receiver -{ -public: - void *DmaPointer() { return &object; } - size_t Size() const { return sizeof(T); } - T& Value() { return object; } -private: - T object; - uint32_t padding; -}; - -// The main network class that drives the network. -class Network -{ -public: - friend class Socket; - - Network(Platform& p); - - void Init(); - void Activate(); - void Exit(); - void Spin(bool full); - void Diagnostics(MessageType mtype); - void Start(); - void Stop(); - - void EnableProtocol(int protocol, int port, int secure, const StringRef& reply); - void DisableProtocol(int protocol, const StringRef& reply); - void ReportProtocols(const StringRef& reply) const; - - void Enable(int mode, const StringRef& ssid, const StringRef& reply); // enable or disable the network - GCodeResult HandleWiFiCode(int mcode, GCodeBuffer& gb, const StringRef& reply, OutputBuffer*& longReply); - bool GetNetworkState(const StringRef& reply); - int EnableState() const; - - void SetHostname(const char *name); - - bool FindResponder(Socket *skt, Port localPort); - - const uint8_t *GetIPAddress() const { return ipAddress; } - void OpenDataPort(Port port); - void TerminateDataPort(); - void DataPortClosing(); - - void HandleHttpGCodeReply(const char *msg); - void HandleTelnetGCodeReply(const char *msg); - void HandleHttpGCodeReply(OutputBuffer *buf); - void HandleTelnetGCodeReply(OutputBuffer *buf); - uint32_t GetHttpReplySeq(); - - // The remaining functions are specific to the WiFi version - WifiFirmwareUploader& GetWifiUploader() { return *uploader; } - - void StartWiFi(); - void ResetWiFi(); - void ResetWiFiForUpload(bool external); - - const char *GetWiFiServerVersion() const { return wiFiServerVersion; } - - const char* TranslateNetworkState() const; - static const char* TranslateWiFiState(WiFiState w); - - void SpiInterrupt(); - void EspRequestsTransfer(); - void UpdateSocketStatus(uint16_t connectedSockets, uint16_t otherEndClosedSockets); - -private: - enum class NetworkState - { - disabled, // WiFi module disabled - starting1, // starting up - starting2, // starting up - active, // running, but not necessarily in the requested mode - changingMode, // running and in the process of switching between modes - }; - - void InitSockets(); - void TerminateSockets(); - void TerminateSockets(Port port); - void StopListening(Port port); - - void StartProtocol(Protocol protocol) - pre(protocol < NumProtocols); - - void ShutdownProtocol(Protocol protocol) - pre(protocol < NumProtocols); - - void ReportOneProtocol(Protocol protocol, const StringRef& reply) const - pre(protocol < NumProtocols); - - void SetIPAddress(const uint8_t ipAddress[], const uint8_t netmask[], const uint8_t gateway[]); - - void SetupSpi(); - - int32_t SendCommand(NetworkCommand cmd, SocketNumber socket, uint8_t flags, const void *dataOut, size_t dataOutLength, void* dataIn, size_t dataInLength); - - template<class T> int32_t SendCommand(NetworkCommand cmd, SocketNumber socket, uint8_t flags, const void *dataOut, size_t dataOutLength, Receiver<T>& recvr) - { - return SendCommand(cmd, socket, flags, dataOut, dataOutLength, recvr.DmaPointer(), recvr.Size()); - } - - void SendListenCommand(Port port, Protocol protocol, unsigned int maxConnections); - void GetNewStatus(); - - static const char* TranslateEspResetReason(uint32_t reason); - - Platform& platform; - NetworkResponder *responders; - NetworkResponder *nextResponderToPoll; - FtpResponder *ftpResponder; - TelnetResponder *telnetResponder; - uint32_t longWait; - uint32_t lastTickMillis; - - WifiFirmwareUploader *uploader; - - Socket sockets[NumTcpSockets]; - size_t currentSocket; - - Port portNumbers[NumProtocols]; // port number used for each protocol - Port ftpDataPort; - bool protocolEnabled[NumProtocols]; // whether each protocol is enabled - - NetworkState state; - WiFiState requestedMode; - WiFiState currentMode; - bool activated; - volatile bool espStatusChanged; - - uint8_t ipAddress[4]; - uint8_t netmask[4]; - uint8_t gateway[4]; - char hostname[16]; // Limit DHCP hostname to 15 characters + terminating 0 - char requestedSsid[SsidLength + 1]; - char actualSsid[SsidLength + 1]; - - unsigned int spiTxUnderruns; - unsigned int spiRxOverruns; - unsigned int reconnectCount; - unsigned int transferAlreadyPendingCount; - unsigned int readyTimeoutCount; - unsigned int responseTimeoutCount; - - char wiFiServerVersion[16]; - - // For processing debug messages from the WiFi module - bool serialRunning; - bool debugPrintPending; - String<100> debugMessageBuffer; -}; - -#endif diff --git a/src/Network2/ESP8266/Socket.cpp b/src/Network2/ESP8266/Socket.cpp deleted file mode 100644 index 7d9a1859..00000000 --- a/src/Network2/ESP8266/Socket.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - * WiFiSocket.cpp - * - * Created on: 22 Apr 2017 - * Author: David - */ - -#include <Network2/ESP8266/Network.h> -#include <Network2/ESP8266/Socket.h> -#include "NetworkBuffer.h" -#include "RepRap.h" - -const uint32_t FindResponderTimeout = 2000; // how long we wait for a responder to become available -const unsigned int MaxBuffersPerSocket = 4; - -Socket::Socket() : localPort(0), receivedData(nullptr), state(SocketState::inactive), needsPolling(false) -{ -} - -void Socket::Init(SocketNumber n) -{ - socketNum = n; - state = SocketState::inactive; - txBufferSpace = 0; -} - -// Close a connection when the last packet has been sent -void Socket::Close() -{ - if (state == SocketState::connected || state == SocketState::clientDisconnecting) - { - const int32_t reply = reprap.GetNetwork().SendCommand(NetworkCommand::connClose, socketNum, 0, nullptr, 0, nullptr, 0); - if (reply == ResponseEmpty) - { - state = (state == SocketState::connected) ? SocketState::closing : SocketState::inactive; - return; - } - } - - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("close failed, in wrong state or bad reply\n"); - } - Terminate(); // something is not right, so terminate the socket for safety -} - -// Terminate a connection immediately -// We can call this after any sort of error on a socket as long as it is in use. -void Socket::Terminate() -{ - if (state != SocketState::inactive) - { - const int32_t reply = reprap.GetNetwork().SendCommand(NetworkCommand::connAbort, socketNum, 0, nullptr, 0, nullptr, 0); - state = (reply != 0) ? SocketState::broken : SocketState::inactive; - } - DiscardReceivedData(); - txBufferSpace = 0; -} - -// Called to terminate the connection unless it is already being closed -void Socket::TerminatePolitely() -{ - if (state != SocketState::clientDisconnecting && state != SocketState::closing) - { - Terminate(); - } -} - -// Return true if there is or may soon be more data to read -bool Socket::CanRead() const -{ - return (state == SocketState::connected) - || (state == SocketState::clientDisconnecting && receivedData != nullptr && receivedData->TotalRemaining() != 0); -} - -// Return true if we can send data to this socket -bool Socket::CanSend() const -{ - return state == SocketState::connected; -} - -// Read 1 character from the receive buffers, returning true if successful -bool Socket::ReadChar(char& c) -{ - if (receivedData != nullptr) - { - const bool ret = receivedData->ReadChar(c); - if (receivedData->IsEmpty()) - { - receivedData = receivedData->Release(); - } - return ret; - } - - c = 0; - return false; -} - -// Return a pointer to data in a buffer and a length available, and mark the data as taken -bool Socket::ReadBuffer(const uint8_t *&buffer, size_t &len) -{ - if (receivedData != nullptr) - { - len = receivedData->Remaining(); - buffer = receivedData->UnreadData(); - return true; - } - - return false; -} - -// Flag some data as taken from the receive buffers. We never take data from more than one buffer at a time. -void Socket::Taken(size_t len) -{ - if (receivedData != nullptr) - { - receivedData->Taken(len); - if (receivedData->IsEmpty()) - { - receivedData = receivedData->Release(); // discard empty buffer at head of chain - } - } -} - -// Poll a socket to see if it needs to be serviced -void Socket::Poll(bool full) -{ - // Get the socket status - Network& network = reprap.GetNetwork(); - Receiver<ConnStatusResponse> resp; - const int32_t ret = network.SendCommand(NetworkCommand::connGetStatus, socketNum, 0, nullptr, 0, resp); - if (ret != (int32_t)resp.Size()) - { - // We can't do much here other than disable and restart wifi, or hope the next status call succeeds - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Bad recv status size\n"); - } - return; - } - - // As well as getting the status for the socket we asked about, we also received bitmaps of connected sockets. - // Pass these to the Network module so that it can avoid polling idle sockets. - network.UpdateSocketStatus(resp.Value().connectedSockets, resp.Value().otherEndClosedSockets); - - switch (resp.Value().state) - { - case ConnState::otherEndClosed: - // Check for further incoming packets before this socket is finally closed. - // This must be done to ensure that FTP uploads are not cut off. - ReceiveData(resp.Value().bytesAvailable); - - if (state == SocketState::clientDisconnecting) - { - // We already got here before, so close the connection once and for all - Close(); - break; - } - else if (state != SocketState::inactive) - { - state = SocketState::clientDisconnecting; - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Client disconnected on socket %u\n", socketNum); - } - break; - } - // We can get here if a client has sent very little data and then instantly closed - // the connection, e.g. when an FTP client transferred very small files over the - // data port. In such cases we must notify the responder about this transmission! - // no break - - case ConnState::connected: - if (full && state != SocketState::connected) - { - // It's a new connection - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("New conn on socket %u for local port %u\n", socketNum, localPort); - } - localPort = resp.Value().localPort; - remotePort = resp.Value().remotePort; - remoteIp = resp.Value().remoteIp; - DiscardReceivedData(); - if (state != SocketState::waitingForResponder) - { - whenConnected = millis(); - state = SocketState::waitingForResponder; - } - if (network.FindResponder(this, localPort)) - { - state = (resp.Value().state == ConnState::connected) ? SocketState::connected : SocketState::clientDisconnecting; - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Found responder\n"); - } - } - else if (millis() - whenConnected >= FindResponderTimeout) - { - Terminate(); - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("No responder, new conn %u terminated\n", socketNum); - } - } - } - - if (state == SocketState::connected) - { - txBufferSpace = resp.Value().writeBufferSpace; - ReceiveData(resp.Value().bytesAvailable); - } - break; - - default: - if (state == SocketState::connected || state == SocketState::waitingForResponder) - { - // Unexpected change of state - if (state != SocketState::clientDisconnecting && reprap.Debug(moduleNetwork)) - { - debugPrintf("Unexpected state change on socket %u\n", socketNum); - } - state = SocketState::broken; - } - else if (state == SocketState::closing) - { - // Socket closed - state = SocketState::inactive; - } - break; - } - - needsPolling = false; -} - -// Try to receive more incoming data from the socket. -void Socket::ReceiveData(uint16_t bytesAvailable) -{ - if (bytesAvailable != 0) - { -// debugPrintf("%u available\n", bytesAvailable); - // First see if we already have a buffer with enough room - NetworkBuffer *const lastBuffer = NetworkBuffer::FindLast(receivedData); - if (lastBuffer != nullptr && (bytesAvailable <= lastBuffer->SpaceLeft() || (lastBuffer->SpaceLeft() != 0 && NetworkBuffer::Count(receivedData) >= MaxBuffersPerSocket))) - { - // Read data into the existing buffer - const size_t maxToRead = min<size_t>(lastBuffer->SpaceLeft(), MaxDataLength); - const int32_t ret = reprap.GetNetwork().SendCommand(NetworkCommand::connRead, socketNum, 0, nullptr, 0, lastBuffer->UnwrittenData(), maxToRead); - if (ret > 0 && (size_t)ret <= maxToRead) - { - lastBuffer->dataLength += (size_t)ret; - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Received %u bytes\n", (unsigned int)ret); - } - } - } - else if (NetworkBuffer::Count(receivedData) < MaxBuffersPerSocket) - { - NetworkBuffer * const buf = NetworkBuffer::Allocate(); - if (buf != nullptr) - { - const size_t maxToRead = min<size_t>(NetworkBuffer::bufferSize, MaxDataLength); - const int32_t ret = reprap.GetNetwork().SendCommand(NetworkCommand::connRead, socketNum, 0, nullptr, 0, buf->Data(), maxToRead); - if (ret > 0 && (size_t)ret <= maxToRead) - { - buf->dataLength = (size_t)ret; - NetworkBuffer::AppendToList(&receivedData, buf); - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Received %u bytes\n", (unsigned int)ret); - } - } - else - { - buf->Release(); - } - } -// else debugPrintf("no buffer\n"); - } - } -} - -// Discard any received data for this transaction -void Socket::DiscardReceivedData() -{ - while (receivedData != nullptr) - { - receivedData = receivedData->Release(); - } -} - -// Send the data, returning the length buffered -size_t Socket::Send(const uint8_t *data, size_t length) -{ - if (state == SocketState::connected && txBufferSpace != 0) - { - const size_t lengthToSend = min<size_t>(length, min<size_t>(txBufferSpace, MaxDataLength)); - const int32_t reply = reprap.GetNetwork().SendCommand(NetworkCommand::connWrite, socketNum, 0, data, lengthToSend, nullptr, 0); - if (reply >= 0 && (size_t)reply <= lengthToSend) - { - txBufferSpace -= (size_t)reply; - return (size_t)reply; - } - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Send failed, terminating\n"); - } - state = SocketState::broken; // something is not right, terminate the socket soon - } - return 0; -} - -// Tell the interface to send the outstanding data -void Socket::Send() -{ - if (state == SocketState::connected) - { - const int32_t reply = reprap.GetNetwork().SendCommand(NetworkCommand::connWrite, socketNum, MessageHeaderSamToEsp::FlagPush, nullptr, 0, nullptr, 0); - if (reply < 0) - { - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Send failed, terminating\n"); - } - state = SocketState::broken; // something is not right, terminate the socket soon - } - } -} - -// Return true if we need to poll this socket -bool Socket::NeedsPolling() const -{ - return state != SocketState::inactive || needsPolling; -} - -// End diff --git a/src/Network2/ESP8266/Socket.h b/src/Network2/ESP8266/Socket.h deleted file mode 100644 index 47cbc780..00000000 --- a/src/Network2/ESP8266/Socket.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * WiFiSocket.h - * - * Created on: 22 Apr 2017 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETWIFI_SOCKET_H_ -#define SRC_DUETNG_DUETWIFI_SOCKET_H_ - -#include "RepRapFirmware.h" -#include "NetworkDefs.h" - -class Socket -{ -public: - Socket(); - void Init(SocketNumber n); - int State() const { return (int)state; } // used only for reporting debug info, hence the 'int' return - void Poll(bool full); - Port GetLocalPort() const { return localPort; } - uint32_t GetRemoteIP() const { return remoteIp; } - Port GetRemotePort() const { return remotePort; } - void Close(); - void Terminate(); - void TerminatePolitely(); - bool ReadChar(char& c); - bool ReadBuffer(const uint8_t *&buffer, size_t &len); - void Taken(size_t len); - bool CanRead() const; - bool CanSend() const; - size_t Send(const uint8_t *data, size_t length); - void Send(); - void SetNeedsPolling() { needsPolling = true; } - bool NeedsPolling() const; - -private: - enum class SocketState : uint8_t - { - inactive, - waitingForResponder, - connected, - clientDisconnecting, - closing, - broken - }; - - void ReInit(); - void ReceiveData(uint16_t bytesAvailable); - void DiscardReceivedData(); - - Port localPort, remotePort; // The local and remote ports - Protocol protocol; // What protocol this socket is for - uint32_t remoteIp; // The remote IP address - NetworkBuffer *receivedData; // List of buffers holding received data - uint32_t whenConnected; - uint16_t txBufferSpace; // How much free transmit buffer space the WiFi mofule reported - SocketNumber socketNum; // The WiFi socket number we are using - SocketState state; - bool needsPolling; -}; - -#endif /* SRC_DUETNG_DUETWIFI_SOCKET_H_ */ diff --git a/src/Network2/ESP8266/WifiFirmwareUploader.cpp b/src/Network2/ESP8266/WifiFirmwareUploader.cpp deleted file mode 100644 index 40861f2c..00000000 --- a/src/Network2/ESP8266/WifiFirmwareUploader.cpp +++ /dev/null @@ -1,766 +0,0 @@ -/* - * EspFirmwareUpload.cpp - * - * Created on: 15 Apr 2016 - * Author: David - */ - -#include "Network.h" -#include "WifiFirmwareUploader.h" -#include "Platform.h" -#include "RepRap.h" -#include "Storage/FileStore.h" - -// ESP8266 command codes -const uint8_t ESP_FLASH_BEGIN = 0x02; -const uint8_t ESP_FLASH_DATA = 0x03; -const uint8_t ESP_FLASH_END = 0x04; -const uint8_t ESP_MEM_BEGIN = 0x05; -const uint8_t ESP_MEM_END = 0x06; -const uint8_t ESP_MEM_DATA = 0x07; -const uint8_t ESP_SYNC = 0x08; -const uint8_t ESP_WRITE_REG = 0x09; -const uint8_t ESP_READ_REG = 0x0a; - -// MAC address storage locations -const uint32_t ESP_OTP_MAC0 = 0x3ff00050; -const uint32_t ESP_OTP_MAC1 = 0x3ff00054; -const uint32_t ESP_OTP_MAC2 = 0x3ff00058; -const uint32_t ESP_OTP_MAC3 = 0x3ff0005c; - -const size_t EspFlashBlockSize = 0x0400; // 1K byte blocks - -const uint8_t ESP_IMAGE_MAGIC = 0xe9; -const uint8_t ESP_CHECKSUM_MAGIC = 0xef; - -const uint32_t ESP_ERASE_CHIP_ADDR = 0x40004984; // &SPIEraseChip -const uint32_t ESP_SEND_PACKET_ADDR = 0x40003c80; // &send_packet -const uint32_t ESP_SPI_READ_ADDR = 0x40004b1c; // &SPIRead -const uint32_t ESP_UNKNOWN_ADDR = 0x40001121; // not used -const uint32_t ESP_USER_DATA_RAM_ADDR = 0x3ffe8000; // &user data ram -const uint32_t ESP_IRAM_ADDR = 0x40100000; // instruction RAM -const uint32_t ESP_FLASH_ADDR = 0x40200000; // address of start of Flash -const uint32_t ESP_FLASH_READ_STUB_BEGIN = IRAM_ADDR + 0x18; - -// Messages corresponding to result codes, should make sense when followed by " error" -const char * const resultMessages[] = -{ - "no", - "timeout", - "comm write", - "connect", - "bad reply", - "file read", - "empty file", - "response header", - "slip frame", - "slip state", - "slip data" -}; - -// A note on baud rates. -// The ESP8266 supports 921600, 460800, 230400, 115200, 74880 and some lower baud rates. -// 921600b is not reliable because even though it sometimes succeeds in connecting, we get a bad response during uploading after a few blocks. -// Probably our UART ISR cannot receive bytes fast enough, perhaps because of the latency of the system tick ISR. -// 460800b doesn't always manage to connect, but if it does then uploading appears to be reliable. -// 230400b always manages to connect. -static const uint32_t uploadBaudRates[] = { 230400, 115200, 74880, 9600 }; - -WifiFirmwareUploader::WifiFirmwareUploader(UARTClass& port) - : uploadPort(port), uploadFile(nullptr), state(UploadState::idle) -{ -} - -bool WifiFirmwareUploader::IsReady() const -{ - return state == UploadState::idle; -} - -void WifiFirmwareUploader::MessageF(const char *fmt, ...) -{ - va_list vargs; - va_start(vargs, fmt); - reprap.GetPlatform().MessageF(FirmwareUpdateMessage, fmt, vargs); - va_end(vargs); -} - -void WifiFirmwareUploader::flushInput() -{ - while (uploadPort.available() != 0) - { - (void)uploadPort.read(); - } -} - -// Extract 1-4 bytes of a value in little-endian order from a buffer beginning at a specified offset -uint32_t WifiFirmwareUploader::getData(unsigned byteCnt, const uint8_t *buf, int ofst) -{ - uint32_t val = 0; - - if (buf && byteCnt) - { - unsigned int shiftCnt = 0; - if (byteCnt > 4) - byteCnt = 4; - do - { - val |= (uint32_t)buf[ofst++] << shiftCnt; - shiftCnt += 8; - } while (--byteCnt); - } - return(val); -} - -// Put 1-4 bytes of a value in little-endian order into a buffer beginning at a specified offset. -void WifiFirmwareUploader::putData(uint32_t val, unsigned byteCnt, uint8_t *buf, int ofst) -{ - if (buf && byteCnt) - { - if (byteCnt > 4) - { - byteCnt = 4; - } - do - { - buf[ofst++] = (uint8_t)(val & 0xff); - val >>= 8; - } while (--byteCnt); - } -} - -// Read a byte optionally performing SLIP decoding. The return values are: -// -// 2 - an escaped byte was read successfully -// 1 - a non-escaped byte was read successfully -// 0 - no data was available -// -1 - the value 0xc0 was encountered (shouldn't happen) -// -2 - a SLIP escape byte was found but the following byte wasn't available -// -3 - a SLIP escape byte was followed by an invalid byte -int WifiFirmwareUploader::ReadByte(uint8_t& data, bool slipDecode) -{ - if (uploadPort.available() == 0) - { - return(0); - } - - // at least one byte is available - data = uploadPort.read(); - if (!slipDecode) - { - return(1); - } - - if (data == 0xc0) - { - // this shouldn't happen - return(-1); - } - - // if not the SLIP escape, we're done - if (data != 0xdb) - { - return(1); - } - - // SLIP escape, check availability of subsequent byte - if (uploadPort.available() == 0) - { - return(-2); - } - - // process the escaped byte - data = uploadPort.read(); - if (data == 0xdc) - { - data = 0xc0; - return(2); - } - - if (data == 0xdd) - { - data = 0xdb; - return(2); - } - // invalid - return(-3); -} - -// When we write a sync packet, there must be no gaps between most of the characters. -// So use this function, which does a block write to the UART buffer in the latest CoreNG. -void WifiFirmwareUploader::writePacketRaw(const uint8_t *buf, size_t len) -{ - uploadPort.write(buf, len); -} - -// Write a byte to the serial port optionally SLIP encoding. Return the number of bytes actually written. -inline void WifiFirmwareUploader::WriteByteRaw(uint8_t b) -{ - uploadPort.write(b); -} - -// Write a byte to the serial port optionally SLIP encoding. Return the number of bytes actually written. -inline void WifiFirmwareUploader::WriteByteSlip(uint8_t b) -{ - if (b == 0xC0) - { - WriteByteRaw(0xDB); - WriteByteRaw(0xDC); - } - else if (b == 0xDB) - { - WriteByteRaw(0xDB); - WriteByteRaw(0xDD); - } - else - { - uploadPort.write(b); - } -} - -// Wait for a data packet to be returned. If the body of the packet is -// non-zero length, return an allocated buffer indirectly containing the -// data and return the data length. Note that if the pointer for returning -// the data buffer is NULL, the response is expected to be two bytes of zero. -// -// If an error occurs, return a negative value. Otherwise, return the number -// of bytes in the response (or zero if the response was not the standard "two bytes of zero"). -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::readPacket(uint8_t op, uint32_t *valp, size_t& bodyLen, uint32_t msTimeout) -{ - enum class PacketState - { - begin = 0, - header, - body, - end, - done - }; - - const size_t headerLength = 8; - - uint32_t startTime = millis(); - uint8_t hdr[headerLength]; - uint16_t hdrIdx = 0; - bodyLen = 0; - uint16_t bodyIdx = 0; - uint8_t respBuf[2]; - - // wait for the response - uint16_t needBytes = 1; - PacketState state = PacketState::begin; - while (state != PacketState::done) - { - uint8_t c; - EspUploadResult stat; - - if (millis() - startTime > msTimeout) - { - return(EspUploadResult::timeout); - } - - if (uploadPort.available() < needBytes) - { - // insufficient data available - // preferably, return to Spin() here - continue; - } - - // sufficient bytes have been received for the current state, process them - switch(state) - { - case PacketState::begin: // expecting frame start - case PacketState::end: // expecting frame end - c = uploadPort.read(); - if (c != 0xc0) - { - return EspUploadResult::slipFrame; - } - if (state == PacketState::begin) - { - state = PacketState::header; - needBytes = 2; - } - else - { - state = PacketState::done; - } - break; - - case PacketState::header: // reading an 8-byte header - case PacketState::body: // reading the response body - { - int rslt; - // retrieve a byte with SLIP decoding - rslt = ReadByte(c, true); - if (rslt != 1 && rslt != 2) - { - // some error occurred - stat = (rslt == 0 || rslt == -2) ? EspUploadResult::slipData : EspUploadResult::slipFrame; - return stat; - } - else if (state == PacketState::header) - { - //store the header byte - hdr[hdrIdx++] = c; - if (hdrIdx >= headerLength) - { - // get the body length, prepare a buffer for it - bodyLen = (uint16_t)getData(2, hdr, 2); - - // extract the value, if requested - if (valp != nullptr) - { - *valp = getData(4, hdr, 4); - } - - if (bodyLen != 0) - { - state = PacketState::body; - } - else - { - needBytes = 1; - state = PacketState::end; - } - } - } - else - { - // Store the response body byte, check for completion - if (bodyIdx < ARRAY_SIZE(respBuf)) - { - respBuf[bodyIdx] = c; - } - ++bodyIdx; - if (bodyIdx >= bodyLen) - { - needBytes = 1; - state = PacketState::end; - } - } - } - break; - - default: // this shouldn't happen - return EspUploadResult::slipState; - } - } - - // Extract elements from the header - const uint8_t resp = (uint8_t)getData(1, hdr, 0); - const uint8_t opRet = (uint8_t)getData(1, hdr, 1); - // Sync packets often provoke a response with a zero opcode instead of ESP_SYNC - if (resp != 0x01 || opRet != op) - { -//debugPrintf("resp %02x %02x\n", resp, opRet); - return EspUploadResult::respHeader; - } - - return EspUploadResult::success; -} - -// Send a block of data performing SLIP encoding of the content. -inline void WifiFirmwareUploader::writePacket(const uint8_t *data, size_t len) -{ - while (len != 0) - { - WriteByteSlip(*data++); - --len; - } -} - -// Send a packet to the serial port while performing SLIP framing. The packet data comprises a header and an optional data block. -// A SLIP packet begins and ends with 0xc0. The data encapsulated has the bytes -// 0xc0 and 0xdb replaced by the two-byte sequences {0xdb, 0xdc} and {0xdb, 0xdd} respectively. -void WifiFirmwareUploader::writePacket(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen) -{ - WriteByteRaw(0xc0); // send the packet start character - writePacket(hdr, hdrLen); // send the header - writePacket(data, dataLen); // send the data block - WriteByteRaw(0xc0); // send the packet end character -} - -// Send a packet to the serial port while performing SLIP framing. The packet data comprises a header and an optional data block. -// This is like writePacket except that it does a fast block write for both the header and the main data with no SLIP encoding. Used to send sync commands. -void WifiFirmwareUploader::writePacketRaw(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen) -{ - WriteByteRaw(0xc0); // send the packet start character - writePacketRaw(hdr, hdrLen); // send the header - writePacketRaw(data, dataLen); // send the data block in raw mode - WriteByteRaw(0xc0); // send the packet end character -} - -// Send a command to the attached device together with the supplied data, if any. -// The data is supplied via a list of one or more segments. -void WifiFirmwareUploader::sendCommand(uint8_t op, uint32_t checkVal, const uint8_t *data, size_t dataLen) -{ - // populate the header - uint8_t hdr[8]; - putData(0, 1, hdr, 0); - putData(op, 1, hdr, 1); - putData(dataLen, 2, hdr, 2); - putData(checkVal, 4, hdr, 4); - - // send the packet - flushInput(); - if (op == ESP_SYNC) - { - writePacketRaw(hdr, sizeof(hdr), data, dataLen); - } - else - { - writePacket(hdr, sizeof(hdr), data, dataLen); - } -} - -// Send a command to the attached device together with the supplied data, if any, and get the response -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::doCommand(uint8_t op, const uint8_t *data, size_t dataLen, uint32_t checkVal, uint32_t *valp, uint32_t msTimeout) -{ - sendCommand(op, checkVal, data, dataLen); - size_t bodyLen; - EspUploadResult stat = readPacket(op, valp, bodyLen, msTimeout); - if (stat == EspUploadResult::success && bodyLen != 2) - { - stat = EspUploadResult::badReply; - } - - return stat; -} - -// Send a synchronising packet to the serial port in an attempt to induce -// the ESP8266 to auto-baud lock on the baud rate. -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::Sync(uint16_t timeout) -{ - uint8_t buf[36]; - - // compose the data for the sync attempt - memset(buf, 0x55, sizeof(buf)); - buf[0] = 0x07; - buf[1] = 0x07; - buf[2] = 0x12; - buf[3] = 0x20; - - EspUploadResult stat = doCommand(ESP_SYNC, buf, sizeof(buf), 0, nullptr, timeout); - - // If we got a response other than sync, discard it and wait for a sync response. This happens at higher baud rates. - for (int i = 0; i < 10 && stat == EspUploadResult::respHeader; ++i) - { - size_t bodyLen; - stat = readPacket(ESP_SYNC, nullptr, bodyLen, timeout); - } - - if (stat == EspUploadResult::success) - { - // Read and discard additional replies - for (;;) - { - size_t bodyLen; - EspUploadResult rc = readPacket(ESP_SYNC, nullptr, bodyLen, defaultTimeout); - if (rc != EspUploadResult::success || bodyLen != 2) - { - break; - } - } - } -//DEBUG -// else debugPrintf("stat=%d\n", (int)stat); - return stat; -} - -// Send a command to the device to begin the Flash process. -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::flashBegin(uint32_t addr, uint32_t size) -{ - // determine the number of blocks represented by the size - const uint32_t blkCnt = (size + EspFlashBlockSize - 1) / EspFlashBlockSize; - - // ensure that the address is on a block boundary - addr &= ~(EspFlashBlockSize - 1); - - // begin the Flash process - uint8_t buf[16]; - putData(size, 4, buf, 0); - putData(blkCnt, 4, buf, 4); - putData(EspFlashBlockSize, 4, buf, 8); - putData(addr, 4, buf, 12); - - uint32_t timeout = (size != 0) ? eraseTimeout : defaultTimeout; - return doCommand(ESP_FLASH_BEGIN, buf, sizeof(buf), 0, nullptr, timeout); -} - -// Send a command to the device to terminate the Flash process -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::flashFinish(bool reboot) -{ - uint8_t buf[4]; - putData(reboot ? 0 : 1, 4, buf, 0); - return doCommand(ESP_FLASH_END, buf, sizeof(buf), 0, nullptr, defaultTimeout); -} - -// Compute the checksum of a block of data -uint16_t WifiFirmwareUploader::checksum(const uint8_t *data, uint16_t dataLen, uint16_t cksum) -{ - if (data != NULL) - { - while (dataLen--) - { - cksum ^= (uint16_t)*data++; - } - } - return(cksum); -} - -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::flashWriteBlock(uint16_t flashParmVal, uint16_t flashParmMask) -{ - const uint32_t blkSize = EspFlashBlockSize; - - // Allocate a data buffer for the combined header and block data - const uint16_t hdrOfst = 0; - const uint16_t dataOfst = 16; - const uint16_t blkBufSize = dataOfst + blkSize; - uint32_t blkBuf32[blkBufSize/4]; - uint8_t * const blkBuf = reinterpret_cast<uint8_t*>(blkBuf32); - - // Prepare the header for the block - putData(blkSize, 4, blkBuf, hdrOfst + 0); - putData(uploadBlockNumber, 4, blkBuf, hdrOfst + 4); - putData(0, 4, blkBuf, hdrOfst + 8); - putData(0, 4, blkBuf, hdrOfst + 12); - - // Get the data for the block - size_t cnt = uploadFile->Read(reinterpret_cast<char *>(blkBuf + dataOfst), blkSize); - if (cnt != blkSize) - { - if (uploadFile->Position() == fileSize) - { - // partial last block, fill the remainder - memset(blkBuf + dataOfst + cnt, 0xff, blkSize - cnt); - } - else - { - return EspUploadResult::fileRead; - } - } - - // Patch the flash parameters into the first block if it is loaded at address 0 - if (uploadBlockNumber == 0 && uploadAddress == 0 && blkBuf[dataOfst] == ESP_IMAGE_MAGIC && flashParmMask != 0) - { - // update the Flash parameters - uint32_t flashParm = getData(2, blkBuf + dataOfst + 2, 0) & ~(uint32_t)flashParmMask; - putData(flashParm | flashParmVal, 2, blkBuf + dataOfst + 2, 0); - } - - // Calculate the block checksum - uint16_t cksum = checksum(blkBuf + dataOfst, blkSize, ESP_CHECKSUM_MAGIC); - EspUploadResult stat; - for (int i = 0; i < 3; i++) - { - if ((stat = doCommand(ESP_FLASH_DATA, blkBuf, blkBufSize, cksum, nullptr, blockWriteTimeout)) == EspUploadResult::success) - { - break; - } - } - - return stat; -} - -WifiFirmwareUploader::EspUploadResult WifiFirmwareUploader::DoErase(uint32_t address, uint32_t size) -{ - const uint32_t sectorsPerBlock = 16; - const uint32_t sectorSize = 4096; - const uint32_t numSectors = (size + sectorSize - 1)/sectorSize; - const uint32_t startSector = address/sectorSize; - uint32_t headSectors = sectorsPerBlock - (startSector % sectorsPerBlock); - - if (numSectors < headSectors) - { - headSectors = numSectors; - } - const uint32_t eraseSize = (numSectors < 2 * headSectors) - ? (numSectors + 1) / 2 * sectorSize - : (numSectors - headSectors) * sectorSize; - - MessageF("Erasing %u bytes...\n", eraseSize); - return flashBegin(uploadAddress, eraseSize); -} - -void WifiFirmwareUploader::Spin() -{ - switch (state) - { - case UploadState::resetting: - if (connectAttemptNumber == ARRAY_SIZE(uploadBaudRates) * retriesPerBaudRate) - { - // Time to give up - reprap.GetNetwork().ResetWiFi(); - uploadResult = EspUploadResult::connect; - state = UploadState::done; - } - else - { - // Reset the serial port at the new baud rate. Also reset the ESP8266. - const uint32_t baud = uploadBaudRates[connectAttemptNumber/retriesPerBaudRate]; - if (connectAttemptNumber % retriesPerBaudRate == 0) - { - // First attempt at this baud rate - MessageF("Trying to connect at %u baud: ", baud); - } - uploadPort.begin(baud); - uploadPort.setInterruptPriority(1); // we are going to move data at seriously high speeds - reprap.GetNetwork().ResetWiFiForUpload(false); - lastAttemptTime = lastResetTime = millis(); - state = UploadState::connecting; - } - break; - - case UploadState::connecting: - if (millis() - lastAttemptTime >= connectAttemptInterval && millis() - lastResetTime >= resetDelay) - { - // Attempt to establish a connection to the ESP8266. - EspUploadResult res = Sync(syncTimeout); - lastAttemptTime = millis(); - if (res == EspUploadResult::success) - { - // Successful connection -// MessageF(" success on attempt %d\n", (connectAttemptNumber % retriesPerBaudRate) + 1); - MessageF(" success\n"); - state = UploadState::erasing1; - } - else - { - // This attempt failed - ++connectAttemptNumber; - if (connectAttemptNumber % retriesPerReset == 0) - { - if (connectAttemptNumber % retriesPerBaudRate == 0) - { - MessageF(" failed\n"); - } - state = UploadState::resetting; // try a reset and a lower baud rate - } - } - } - break; - - case UploadState::erasing1: - if (millis() - lastAttemptTime >= blockWriteInterval) - { - uploadResult = DoErase(systemParametersAddress, systemParametersSize); - if (uploadResult == EspUploadResult::success) - { - state = UploadState::erasing2; - } - else - { - MessageF("Erase failed\n"); - state = UploadState::done; - } - } - break; - - case UploadState::erasing2: - if (millis() - lastAttemptTime >= blockWriteInterval) - { - uploadResult = DoErase(uploadAddress, fileSize); - if (uploadResult == EspUploadResult::success) - { - MessageF("Uploading file...\n"); - uploadBlockNumber = 0; - uploadNextPercentToReport = percentToReportIncrement; - lastAttemptTime = millis(); - state = UploadState::uploading; - } - else - { - MessageF("Erase failed\n"); - state = UploadState::done; - } - } - break; - - case UploadState::uploading: - // The ESP needs several milliseconds to recover from one packet before it will accept another - if (millis() - lastAttemptTime >= blockWriteInterval) - { - const uint32_t blkCnt = (fileSize + EspFlashBlockSize - 1) / EspFlashBlockSize; - if (uploadBlockNumber < blkCnt) - { - uploadResult = flashWriteBlock(0, 0); - lastAttemptTime = millis(); - if (uploadResult != EspUploadResult::success) - { - MessageF("Flash block upload failed\n"); - state = UploadState::done; - } - const unsigned int percentComplete = (100 * uploadBlockNumber)/blkCnt; - ++uploadBlockNumber; - if (percentComplete >= uploadNextPercentToReport) - { - MessageF("%u%% complete\n", percentComplete); - uploadNextPercentToReport += percentToReportIncrement; - } - } - else - { - state = UploadState::done; - } - } - break; - - case UploadState::done: - uploadFile->Close(); - uploadPort.end(); // disable the port, it has a high interrupt priority - if (uploadResult == EspUploadResult::success) - { - reprap.GetPlatform().Message(FirmwareUpdateMessage, "Upload successful\n"); - if (restartModeOnCompletion == 1) - { - reprap.GetNetwork().Start(); - } - else - { - reprap.GetNetwork().ResetWiFi(); - } - } - else - { - MessageF("Error: Installation failed due to %s error\n", resultMessages[(size_t)uploadResult]); - // Not safe to restart the network - reprap.GetNetwork().ResetWiFi(); - } - state = UploadState::idle; - break; - - default: - break; - } -} - -// Try to upload the given file at the given address -void WifiFirmwareUploader::SendUpdateFile(const char *file, const char *dir, uint32_t address) -{ - Platform& platform = reprap.GetPlatform(); - uploadFile = platform.OpenFile(dir, file, OpenMode::read); - if (uploadFile == nullptr) - { - MessageF("Failed to open file %s\n", file); - return; - } - - fileSize = uploadFile->Length(); - if (fileSize == 0) - { - uploadFile->Close(); - MessageF("Upload file is empty %s\n", file); - return; - } - - // Stop the network - Network& network = reprap.GetNetwork(); - restartModeOnCompletion = network.EnableState(); - network.Stop(); - - // Set up the state so that subsequent calls to Spin() will attempt the upload - uploadAddress = address; - connectAttemptNumber = 0; - state = UploadState::resetting; -} - -// End diff --git a/src/Network2/ESP8266/WifiFirmwareUploader.h b/src/Network2/ESP8266/WifiFirmwareUploader.h deleted file mode 100644 index 1fd4195b..00000000 --- a/src/Network2/ESP8266/WifiFirmwareUploader.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * EspFirmwareUpload.h - * - * Created on: 15 Apr 2016 - * Author: David - */ - -#ifndef SRC_DUETNG_WIFIFIRMWAREUPLOADER_H_ -#define SRC_DUETNG_WIFIFIRMWAREUPLOADER_H_ - -#include "RepRapFirmware.h" - -class WifiFirmwareUploader -{ -public: - WifiFirmwareUploader(UARTClass& port); - bool IsReady() const; - void SendUpdateFile(const char *file, const char *dir, uint32_t address); - void Spin(); - - static const uint32_t FirmwareAddress = 0x00000000; - static const uint32_t WebFilesAddress = 0x00100000; - -private: - static const uint32_t defaultTimeout = 500; // default timeout in milliseconds - static const uint32_t syncTimeout = 1000; - static const unsigned int retriesPerBaudRate = 9; - static const unsigned int retriesPerReset = 3; - static const uint32_t connectAttemptInterval = 50; - static const uint32_t resetDelay = 500; - static const uint32_t blockWriteInterval = 15; // 15ms is long enough, 10ms is mostly too short - static const uint32_t blockWriteTimeout = 200; - static const uint32_t eraseTimeout = 15000; // increased from 12 to 15 seconds because Roland's board was timing out - static const unsigned int percentToReportIncrement = 5; // how often we report % complete - static const uint32_t systemParametersAddress = 0x3FE000; // the address of the system + user parameter area that needs to be cleared when changing SDK version - static const uint32_t systemParametersSize = 0x2000; // the size of the system + user parameter area - - // Return codes - this list must be kept in step with the corresponding messages - enum class EspUploadResult - { - success = 0, - timeout, - connect, - badReply, - fileRead, - emptyFile, - respHeader, - slipFrame, - slipState, - slipData, - }; - - enum class UploadState - { - idle, - resetting, - connecting, - erasing1, - erasing2, - uploading, - done - }; - - void MessageF(const char *fmt, ...); - uint32_t getData(unsigned byteCnt, const uint8_t *buf, int ofst); - void putData(uint32_t val, unsigned byteCnt, uint8_t *buf, int ofst); - int ReadByte(uint8_t& data, bool slipDecode); - void WriteByteRaw(uint8_t b); - void WriteByteSlip(uint8_t b); - void flushInput(); - EspUploadResult readPacket(uint8_t op, uint32_t *valp, size_t& bodyLen, uint32_t msTimeout); - void writePacket(const uint8_t *data, size_t len); - void writePacketRaw(const uint8_t *buf, size_t len); - void writePacket(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen); - void writePacketRaw(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen); - void sendCommand(uint8_t op, uint32_t checkVal, const uint8_t *data, size_t dataLen); - EspUploadResult doCommand(uint8_t op, const uint8_t *data, size_t dataLen, uint32_t checkVal, uint32_t *valp, uint32_t msTimeout); - EspUploadResult Sync(uint16_t timeout); - EspUploadResult flashBegin(uint32_t addr, uint32_t size); - EspUploadResult flashFinish(bool reboot); - static uint16_t checksum(const uint8_t *data, uint16_t dataLen, uint16_t cksum); - EspUploadResult flashWriteBlock(uint16_t flashParmVal, uint16_t flashParmMask); - EspUploadResult DoErase(uint32_t address, uint32_t size); - - UARTClass& uploadPort; - FileStore *uploadFile; - FilePosition fileSize; - uint32_t uploadAddress; - uint32_t uploadBlockNumber; - unsigned int uploadNextPercentToReport; - unsigned int connectAttemptNumber; - uint32_t lastAttemptTime; - uint32_t lastResetTime; - UploadState state; - EspUploadResult uploadResult; - int restartModeOnCompletion; -}; - -#endif /* SRC_DUETNG_WIFIFIRMWAREUPLOADER_H_ */ diff --git a/src/Network2/FirmwareUpdater.cpp b/src/Network2/FirmwareUpdater.cpp deleted file mode 100644 index 324894db..00000000 --- a/src/Network2/FirmwareUpdater.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * FirmwareUpdater.cpp - * - * Created on: 21 May 2016 - * Author: David - */ - -#include "FirmwareUpdater.h" - -#include "RepRapFirmware.h" -#include "Network.h" -#include "Platform.h" -#include "RepRap.h" - -#ifdef DUET_WIFI -#include "WifiFirmwareUploader.h" -#endif - -namespace FirmwareUpdater -{ - const unsigned int WifiFirmwareModule = 1; - const unsigned int WifiFilesModule = 2; - const unsigned int WifiExternalFirmwareModule = 3; - - // Check that the prerequisites are satisfied. - // Return true if yes, else print a message and return false. - bool CheckFirmwareUpdatePrerequisites(uint8_t moduleMap, const StringRef& reply) - { -#ifdef DUET_WIFI - if ((moduleMap & (1 << WifiExternalFirmwareModule)) != 0 && (moduleMap & ((1 << WifiFirmwareModule) | (1 << WifiFilesModule))) != 0) - { - reply.copy("Invalid combination of firmware update modules"); - return false; - } - if ((moduleMap & (1 << WifiFirmwareModule)) != 0 && !reprap.GetPlatform().GetMassStorage()->FileExists(SYS_DIR, WIFI_FIRMWARE_FILE)) - { - reply.printf("File %s not found", WIFI_FIRMWARE_FILE); - return false; - } - if ((moduleMap & (1 << WifiFilesModule)) != 0 && !reprap.GetPlatform().GetMassStorage()->FileExists(SYS_DIR, WIFI_WEB_FILE)) - { - reply.printf("File %s not found", WIFI_WEB_FILE); - return false; - } -#endif - return true; - } - - bool IsReady() - { -#ifdef DUET_WIFI - return reprap.GetNetwork().GetWifiUploader().IsReady(); -#else - return true; -#endif - } - - void UpdateModule(unsigned int module) - { -#ifdef DUET_WIFI - switch(module) - { - case WifiExternalFirmwareModule: - reprap.GetNetwork().ResetWiFiForUpload(true); - break; - - case WifiFirmwareModule: - reprap.GetNetwork().GetWifiUploader().SendUpdateFile(WIFI_FIRMWARE_FILE, SYS_DIR, WifiFirmwareUploader::FirmwareAddress); - break; - - case WifiFilesModule: - reprap.GetNetwork().GetWifiUploader().SendUpdateFile(WIFI_WEB_FILE, SYS_DIR, WifiFirmwareUploader::WebFilesAddress); - break; - } -#endif - } -} - -// End diff --git a/src/Network2/FirmwareUpdater.h b/src/Network2/FirmwareUpdater.h deleted file mode 100644 index 82104e73..00000000 --- a/src/Network2/FirmwareUpdater.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * FirmwareUpdater.h - * - * Created on: 21 May 2016 - * Author: David - */ - -#ifndef SRC_DUETNG_FIRMWAREUPDATER_H_ -#define SRC_DUETNG_FIRMWAREUPDATER_H_ - -#include <cstdint> -#include "Libraries/General/StringRef.h" - -namespace FirmwareUpdater -{ - bool CheckFirmwareUpdatePrerequisites(uint8_t moduleMap, const StringRef& reply); - bool IsReady(); - void UpdateModule(unsigned int module); -} - -#endif /* SRC_DUETNG_FIRMWAREUPDATER_H_ */ diff --git a/src/Network2/FtpResponder.cpp b/src/Network2/FtpResponder.cpp deleted file mode 100644 index 82c01ac6..00000000 --- a/src/Network2/FtpResponder.cpp +++ /dev/null @@ -1,911 +0,0 @@ -/* - * FtpResponder.cpp - * - * Created on: 15 Apr 2017 - * Authors: David and Christian - */ - -#include "FtpResponder.h" -#include "Network.h" -#include "Platform.h" - -FtpResponder::FtpResponder(NetworkResponder *n) : NetworkResponder(n), dataSocket(nullptr), - passivePort(0), passivePortOpenTime(0), dataBuf(nullptr) -{ - strcpy(fileToMove, ""); -} - -// Ask the responder to accept this connection, returns true if it did -bool FtpResponder::Accept(Socket *s, Protocol protocol) -{ - if (responderState == ResponderState::free && protocol == FtpProtocol) - { - // Make sure we can get an output buffer before we accept the connection, or we won't be able to reply - if (outBuf != nullptr || OutputBuffer::Allocate(outBuf)) - { - clientPointer = 0; - skt = s; - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("FTP connection accepted\n"); - } - - outBuf->copy("220 RepRapFirmware FTP server\r\n"); - Commit(ResponderState::authenticating); - return true; - } - } - else if (responderState == ResponderState::waitingForPasvPort && protocol == FtpDataProtocol && s->GetLocalPort() == passivePort) - { - dataSocket = s; - responderState = ResponderState::pasvPortOpened; - - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("FTP data connection accepted\n"); - } - return true; - } - return false; -} - -// This is called to force termination if we implement the specified protocol -void FtpResponder::Terminate(Protocol protocol) -{ - if (responderState != ResponderState::free && (protocol == FtpProtocol || protocol == AnyProtocol)) - { - ConnectionLost(); - } -} - -// Do some work, returning true if we did anything significant -bool FtpResponder::Spin() -{ - switch (responderState) - { - case ResponderState::free: - return false; - - case ResponderState::authenticating: - case ResponderState::reading: - return ReadData(); - - case ResponderState::sending: - SendData(); - return true; - - case ResponderState::waitingForPasvPort: - if (millis() - passivePortOpenTime > ftpPasvPortTimeout && (outBuf != nullptr || OutputBuffer::Allocate(outBuf))) - { - outBuf->copy("425 Failed to establish connection.\r\n"); - Commit(ResponderState::reading); - - CloseDataPort(); - return true; - } - return false; - - case ResponderState::pasvPortOpened: - if (dataBuf != nullptr || OutputBuffer::Allocate(dataBuf)) - { - return ReadData(); - } - return false; - - case ResponderState::uploading: - DoUpload(); - - if (!uploadError && skt->CanRead()) - { - ReadData(); // check for incoming ABOR requests - } - return true; - - case ResponderState::sendingPasvData: - SendPassiveData(); - - if (!sendError && skt->CanRead()) - { - ReadData(); // check for incoming ABOR requests - } - return true; - - case ResponderState::pasvTransferComplete: - if (outBuf != nullptr || OutputBuffer::Allocate(outBuf)) - { - // Is the main FTP connection still available? - if (skt->CanSend()) - { - // Yes - send a response - if (uploadError || sendError) - { - outBuf->copy("526 Transfer failed!\r\n"); - } - else - { - outBuf->copy("226 Transfer complete.\r\n"); - } - Commit(ResponderState::reading); - - // Close the data port again - CloseDataPort(); - } - else - { - // No - reset our state - ConnectionLost(); - } - - return true; - } - return false; - - default: // should not happen - return false; - } -} - -void FtpResponder::Diagnostics(MessageType mt) const -{ - GetPlatform().MessageF(mt, " FTP(%d)", (int)responderState); -} - -// This must be called only for the main FTP port -void FtpResponder::ConnectionLost() -{ - CloseDataPort(); - NetworkResponder::ConnectionLost(); -} - -// Send our data over the main FTP port. -// We send outBuf first and then outStack. fileBeingSent is reserved for the data port. -void FtpResponder::SendData() -{ - // Send our output buffer and output stack - for(;;) - { - if (outBuf == nullptr) - { - outBuf = outStack->Pop(); - if (outBuf == nullptr) - { - break; - } - } - const size_t bytesLeft = outBuf->BytesLeft(); - if (bytesLeft == 0) - { - outBuf = OutputBuffer::Release(outBuf); - } - else - { - const size_t sent = skt->Send(reinterpret_cast<const uint8_t *>(outBuf->UnreadData()), bytesLeft); - if (sent == 0) - { - // Check whether the connection has been closed - if (!skt->CanSend()) - { - // The connection has been lost or the other end has closed it - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Can't send anymore\n"); - } - ConnectionLost(); - } - return; - } - - outBuf->Taken(sent); // tell the output buffer how much data we have taken - if (sent < bytesLeft) - { - return; - } - outBuf = OutputBuffer::Release(outBuf); - } - } - - // If we get here then there is nothing left to send - skt->Send(); // tell the socket there is no more data - - // If we are going to free up this responder after sending, then we must close the connection - if (stateAfterSending == ResponderState::free) - { - skt->Close(); - skt = nullptr; - } - responderState = stateAfterSending; -} - -// Send our data over the passive FTP data port. -// We send dataBuf first and then fileBeingSent. -void FtpResponder::SendPassiveData() -{ - // Send our output buffers - while (dataBuf != nullptr) - { - const size_t bytesLeft = dataBuf->BytesLeft(); - if (bytesLeft == 0) - { - dataBuf = OutputBuffer::Release(dataBuf); - } - else - { - const size_t sent = dataSocket->Send(reinterpret_cast<const uint8_t *>(dataBuf->UnreadData()), bytesLeft); - if (sent == 0) - { - // Check whether the connection has been closed - if (!dataSocket->CanSend()) - { - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Can't send anymore over the data port\n"); - } - - sendError = true; - dataSocket = nullptr; - if (fileBeingSent != nullptr) - { - fileBeingSent->Close(); - fileBeingSent = nullptr; - } - - responderState = ResponderState::pasvTransferComplete; - } - return; - } - - // Tell the output buffer how much data we have taken - dataBuf->Taken(sent); - if (sent < bytesLeft) - { - return; - } - dataBuf = OutputBuffer::Release(dataBuf); - } - } - - // If we get here then there are no output buffers left to send - // If we have a file to send, send it - if (fileBeingSent != nullptr && fileBuffer == nullptr) - { - fileBuffer = NetworkBuffer::Allocate(); - if (fileBuffer == nullptr) - { - return; // no buffer available, try again later - } - } - - // If we have a file buffer here, we must be in the process of sending a file - while (fileBuffer != nullptr) - { - if (fileBuffer->IsEmpty() && fileBeingSent != nullptr) - { - const int bytesRead = fileBuffer->ReadFromFile(fileBeingSent); - if (bytesRead != (int)NetworkBuffer::bufferSize) - { - // We had a read error or we reached the end of the file - fileBeingSent->Close(); - fileBeingSent = nullptr; - } - } - - if (fileBuffer->IsEmpty()) - { - // Must have sent the whole file - fileBuffer->Release(); - fileBuffer = nullptr; - } - else - { - const size_t remaining = fileBuffer->Remaining(); - const size_t sent = dataSocket->Send(fileBuffer->UnreadData(), remaining); - if (sent == 0) - { - // Check whether the connection has been closed - if (!dataSocket->CanSend()) - { - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Can't send anymore\n"); - } - - sendError = true; - dataSocket = nullptr; - if (fileBeingSent != nullptr) - { - fileBeingSent->Close(); - fileBeingSent = nullptr; - } - fileBuffer->Release(); - fileBuffer = nullptr; - - responderState = ResponderState::pasvTransferComplete; - } - return; - } - - fileBuffer->Taken(sent); - if (sent < remaining) - { - return; - } - } - } - - // If we get here then there is nothing left to send. Close it as well - dataSocket->Send(); // tell the socket there is no more data - dataSocket->Close(); - dataSocket = nullptr; - - responderState = ResponderState::pasvTransferComplete; -} - -// Write some more upload data -void FtpResponder::DoUpload() -{ - // Write incoming data to the file - const uint8_t *buffer; - size_t len; - if (dataSocket->ReadBuffer(buffer, len)) - { - if (reprap.Debug(moduleWebserver)) - { - GetPlatform().MessageF(UsbMessage, "Writing %u bytes of upload data\n", len); - } - - dataSocket->Taken(len); - if (!fileBeingUploaded.Write(buffer, len)) - { - uploadError = true; - GetPlatform().Message(ErrorMessage, "Could not write upload data!\n"); - CancelUpload(); - - responderState = ResponderState::pasvTransferComplete; - return; - } - } - - // Upload has finished if the connection is closed - if (!dataSocket->CanRead()) - { - dataSocket = nullptr; - responderState = ResponderState::pasvTransferComplete; - - FinishUpload(0, 0); - } -} - -// Try to read some data from the main FTP port and return true -// if anything significant could be done -bool FtpResponder::ReadData() -{ - bool readSomething = false; - char c; - while (!haveCompleteLine && skt->ReadChar(c)) - { - CharFromClient(c); - readSomething = true; - } - - if (!readSomething && !skt->CanRead()) - { - ConnectionLost(); - return true; - } - - if (haveCompleteLine && (outBuf != nullptr || OutputBuffer::Allocate(outBuf))) - { - ProcessLine(); - return true; - } - return readSomething; -} - -// Keep track of incoming characters -void FtpResponder::CharFromClient(char c) -{ - switch (c) - { - case 0: - break; - - case '\r': - case '\n': - if (clientPointer != 0) - { - // This line is complete - clientMessage[clientPointer] = 0; - haveCompleteLine = true; - } - break; - - default: - clientMessage[clientPointer++] = c; - - // Make sure we don't overflow the line buffer - if (clientPointer > ARRAY_UPB(clientMessage)) - { - clientPointer = 0; - GetPlatform().Message(UsbMessage, "Webserver: Buffer overflow in FTP server!\n"); - } - break; - } -} - -// Process the next FTP command -void FtpResponder::ProcessLine() -{ - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("FTP request '%s' (state %d)\n", clientMessage, (int)responderState); - } - - haveCompleteLine = false; - clientPointer = 0; - - switch (responderState) - { - case ResponderState::authenticating: - // don't check the user name - if (StringStartsWith(clientMessage, "USER")) - { - outBuf->copy("331 Please specify the password.\r\n"); - Commit(ResponderState::authenticating); - } - // but check the password (if set) - else if (StringStartsWith(clientMessage, "PASS")) - { - const char *password = GetParameter("PASS"); - if (reprap.NoPasswordSet() || reprap.CheckPassword(password)) - { - strcpy(currentDirectory, "/"); - - outBuf->copy("230 Login successful.\r\n"); - Commit(ResponderState::reading); - } - else - { - outBuf->copy("530 Login incorrect.\r\n"); - Commit(); - } - } - // end connection - else if (StringEquals(clientMessage, "QUIT")) - { - outBuf->copy("221 Goodbye.\r\n"); - Commit(); - } - // if it's different, send response 500 to indicate we don't know the code (might be AUTH or so) - else - { - outBuf->copy("500 Unknown login command.\r\n"); - Commit(ResponderState::authenticating); - } - break; - - case ResponderState::reading: - // get system type - if (StringEquals(clientMessage, "SYST")) - { - outBuf->copy("215 UNIX Type: L8\r\n"); - Commit(ResponderState::reading); - } - // get features - else if (StringEquals(clientMessage, "FEAT")) - { - outBuf->copy( "211-Features:\r\n" - "PASV\r\n" // support PASV mode - "211 End\r\n" - ); - Commit(ResponderState::reading); - } - // get current dir - else if (StringEquals(clientMessage, "PWD")) - { - outBuf->printf("257 \"%s\"\r\n", currentDirectory); - Commit(ResponderState::reading); - } - // set current dir - else if (StringStartsWith(clientMessage, "CWD")) - { - const char *directory = GetParameter("CWD"); - ChangeDirectory(directory); - } - // change to parent of current directory - else if (StringEquals(clientMessage, "CDUP")) - { - ChangeDirectory(".."); - } - // switch transfer mode (sends response, but doesn't have any effects) - else if (StringStartsWith(clientMessage, "TYPE")) - { - const char *type = GetParameter("TYPE"); - if (StringEquals(type, "I")) - { - outBuf->copy("200 Switching to Binary mode.\r\n"); - } - else if (StringEquals(type, "A")) - { - outBuf->copy("200 Switching to ASCII mode.\r\n"); - } - else - { - outBuf->copy("500 Unknown command.\r\n"); - } - Commit(ResponderState::reading); - } - // enter passive mode mode - else if (StringEquals(clientMessage, "PASV")) - { - // reset error conditions - uploadError = sendError = false; - - // open random port > 1023 - passivePort = random(1024, 65535); - passivePortOpenTime = millis(); - - GetNetwork().OpenDataPort(passivePort); - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("FTP data port open at port %u\n", passivePort); - } - - // send FTP response - const uint8_t * const ipAddress = GetNetwork().GetIPAddress(); - outBuf->printf("227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", - ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3], - passivePort / 256, passivePort % 256); - Commit(ResponderState::waitingForPasvPort); - } - // PASV commands are not supported in this state - else if (StringStartsWith(clientMessage, "LIST") || StringStartsWith(clientMessage, "RETR") || StringStartsWith(clientMessage, "STOR")) - { - outBuf->copy("425 Use PASV first.\r\n"); - Commit(ResponderState::reading); - } - // delete file - else if (StringStartsWith(clientMessage, "DELE")) - { - const char *filename = GetParameter("DELE"); - if (GetPlatform().GetMassStorage()->Delete(currentDirectory, filename)) - { - outBuf->copy("250 Delete operation successful.\r\n"); - } - else - { - outBuf->copy("550 Delete operation failed.\r\n"); - } - Commit(ResponderState::reading); - } - // delete directory - else if (StringStartsWith(clientMessage, "RMD")) - { - const char *filename = GetParameter("RMD"); - if (GetPlatform().GetMassStorage()->Delete(currentDirectory, filename)) - { - outBuf->copy("250 Remove directory operation successful.\r\n"); - } - else - { - outBuf->copy("550 Remove directory operation failed.\r\n"); - } - Commit(ResponderState::reading); - } - // make new directory - else if (StringStartsWith(clientMessage, "MKD")) - { - const char *filename = GetParameter("MKD"); - const char *location = (filename[0] == '/') - ? filename - : GetPlatform().GetMassStorage()->CombineName(currentDirectory, filename); - - if (GetPlatform().GetMassStorage()->MakeDirectory(location)) - { - outBuf->printf("257 \"%s\" created\r\n", location); - } - else - { - outBuf->copy("550 Create directory operation failed.\r\n"); - } - Commit(ResponderState::reading); - } - // rename file or directory - else if (StringStartsWith(clientMessage, "RNFR")) - { - const char *filename = GetParameter("RNFR"); - if (filename[0] != '/') - { - filename = GetPlatform().GetMassStorage()->CombineName(currentDirectory, filename); - } - SafeStrncpy(fileToMove, filename, ARRAY_SIZE(fileToMove)); - - if (GetPlatform().GetMassStorage()->FileExists(fileToMove)) - { - outBuf->copy("350 Ready to RNTO.\r\n"); - } - else - { - outBuf->copy("550 Invalid file or directory.\r\n"); - } - Commit(ResponderState::reading); - } - else if (StringStartsWith(clientMessage, "RNTO")) - { - const char *filename = GetParameter("RNTO"); - if (filename[0] != '/') - { - filename = GetPlatform().GetMassStorage()->CombineName(currentDirectory, filename); - } - - if (GetPlatform().GetMassStorage()->Rename(fileToMove, filename)) - { - outBuf->copy("250 Rename successful.\r\n"); - } - else - { - outBuf->copy("500 Could not rename file or directory\r\n"); - } - Commit(ResponderState::reading); - } - // no op - else if (StringEquals(clientMessage, "NOOP")) - { - outBuf->copy("200 NOOP okay.\r\n"); - Commit(ResponderState::reading); - } - // end connection - else if (StringEquals(clientMessage, "QUIT")) - { - outBuf->copy("221 Goodbye.\r\n"); - Commit(); - } - // unknown - else - { - outBuf->copy("500 Unknown command.\r\n"); - Commit(ResponderState::reading); - } - break; - - case ResponderState::pasvPortOpened: - // list directory entries - if (StringStartsWith(clientMessage, "LIST")) - { - // send announcement via ftp main port - outBuf->copy("150 Here comes the directory listing.\r\n"); - Commit(ResponderState::sendingPasvData); - - // build directory listing, dataBuf is sent later in the Spin loop - MassStorage * const massStorage = GetPlatform().GetMassStorage(); - FileInfo fileInfo; - if (massStorage->FindFirst(currentDirectory, fileInfo)) - { - do { - // Example for a typical UNIX-like file list: - // "drwxr-xr-x 2 ftp ftp 0 Apr 11 2013 bin\r\n" - const char dirChar = (fileInfo.isDirectory) ? 'd' : '-'; - const struct tm * const timeInfo = gmtime(&fileInfo.lastModified); - dataBuf->catf("%crw-rw-rw- 1 ftp ftp %13lu %s %02d %04d %s\r\n", - dirChar, fileInfo.size, massStorage->GetMonthName(timeInfo->tm_mon + 1), - timeInfo->tm_mday, timeInfo->tm_year + 1900, fileInfo.fileName); - } while (massStorage->FindNext(fileInfo)); - } - } - // switch transfer mode (sends response, but doesn't have any effects) - else if (StringStartsWith(clientMessage, "TYPE")) - { - const char *type = GetParameter("TYPE"); - if (StringEquals(type, "I")) - { - outBuf->copy("200 Switching to Binary mode.\r\n"); - } - else if (StringEquals(type, "A")) - { - outBuf->copy("200 Switching to ASCII mode.\r\n"); - } - else - { - outBuf->copy("500 Unknown command.\r\n"); - } - Commit(ResponderState::pasvPortOpened); - } - // upload a file - else if (StringStartsWith(clientMessage, "STOR")) - { - const char *filename = GetParameter("STOR"); - FileStore *file = GetPlatform().OpenFile(currentDirectory, filename, OpenMode::write); - if (file != nullptr) - { - StartUpload(file, filename); - - outBuf->copy("150 OK to send data.\r\n"); - Commit(ResponderState::uploading); - } - else - { - outBuf->copy("550 Failed to open file.\r\n"); - Commit(ResponderState::reading); - } - } - // download a file - else if (StringStartsWith(clientMessage, "RETR")) - { - const char *filename = GetParameter("RETR"); - fileBeingSent = GetPlatform().OpenFile(currentDirectory, filename, OpenMode::read); - if (fileBeingSent != nullptr) - { - outBuf->printf("150 Opening data connection for %s (%lu bytes).\r\n", filename, fileBeingSent->Length()); - Commit(ResponderState::sendingPasvData); - } - else - { - outBuf->copy("550 Failed to open file.\r\n"); - Commit(ResponderState::reading); - } - } - // abort current operation - else if (StringEquals(clientMessage, "ABOR")) - { - CloseDataPort(); - - outBuf->copy("226 ABOR successful.\r\n"); - Commit(ResponderState::reading); - } - // end connection - else if (StringEquals(clientMessage, "QUIT")) - { - CloseDataPort(); - - outBuf->copy("221 Goodbye.\r\n"); - Commit(); - } - // unknown command - else - { - outBuf->copy("500 Unknown command.\r\n"); - Commit(ResponderState::pasvPortOpened); - } - break; - - case ResponderState::uploading: - case ResponderState::sendingPasvData: - // abort current transfer - if (StringEquals(clientMessage, "ABOR")) - { - CancelUpload(); - CloseDataPort(); - - outBuf->copy("226 ABOR successful.\r\n"); - Commit(ResponderState::reading); - } - // in theory we could add support for QUIT here but it's not worth the effort - // unknown command - else - { - outBuf->copy("500 Unknown command.\r\n"); - Commit(responderState); - } - break; - - default: - // do nothing - break; - } -} - -const char *FtpResponder::GetParameter(const char *after) const -{ - const size_t commandLength = strlen(after); - if (commandLength >= ftpMessageLength) - { - return ""; - } - - const char *result = clientMessage + strlen(after) + 1; - while ((*result == '\t' || *result == ' ') && *result != 0) - { - ++result; - } - return result; -} - -void FtpResponder::ChangeDirectory(const char *newDirectory) -{ - char combinedPath[MaxFilenameLength]; - if (newDirectory[0] != 0) - { - // Prepare the new directory path - if (newDirectory[0] == '/') // Absolute path - { - SafeStrncpy(combinedPath, newDirectory, ARRAY_SIZE(combinedPath)); - } - else if (StringEquals(newDirectory, ".")) - { - SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath)); - } - else if (StringEquals(newDirectory, "..")) // Go up - { - // Check if we're already at the root directory - if (StringEquals(currentDirectory, "/")) - { - outBuf->copy("550 Failed to change directory.\r\n"); - Commit(responderState); - return; - } - - // No - find the parent directory - SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath)); - for(int i = strlen(combinedPath) - 2; i >= 0; i--) - { - if (combinedPath[i] == '/') - { - combinedPath[i + 1] = 0; - break; - } - } - } - else // Go to child directory - { - SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath)); - if (!StringEndsWith(combinedPath, "/") && strlen(combinedPath) > 1) - { - SafeStrncat(combinedPath, "/", ARRAY_SIZE(combinedPath)); - } - SafeStrncat(combinedPath, newDirectory, ARRAY_SIZE(combinedPath)); - } - - // Make sure the new path does not end with a slash, else FatFs won't be able to see the directory - if (StringEndsWith(combinedPath, "/") && strlen(combinedPath) > 1) - { - combinedPath[strlen(combinedPath) - 1] = 0; - } - - // Verify the final path and change it if possible - if (GetPlatform().GetMassStorage()->DirectoryExists(combinedPath)) - { - SafeStrncpy(currentDirectory, combinedPath, ARRAY_SIZE(currentDirectory)); - outBuf->copy("250 Directory successfully changed.\r\n"); - Commit(responderState); - } - else - { - outBuf->copy("550 Failed to change directory.\r\n"); - Commit(responderState); - } - } - else - { - outBuf->copy("550 Failed to change directory.\r\n"); - Commit(responderState); - } -} - -void FtpResponder::CloseDataPort() -{ - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("FTP data port is being closed\n"); - } - - if (dataSocket != nullptr) - { - GetNetwork().DataPortClosing(); - dataSocket->Close(); // close it gracefully - dataSocket = nullptr; - } - else - { - GetNetwork().TerminateDataPort(); // in case it has been partially set up - } - - OutputBuffer::ReleaseAll(dataBuf); - dataBuf = nullptr; - - if (fileBeingSent != nullptr) - { - fileBeingSent->Close(); - fileBeingSent = nullptr; - } -} - -// End diff --git a/src/Network2/FtpResponder.h b/src/Network2/FtpResponder.h deleted file mode 100644 index e98a1d50..00000000 --- a/src/Network2/FtpResponder.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * FtpResponder.h - * - * Created on: 14 Apr 2017 - * Authors: David and Christian - */ - -#ifndef SRC_DUETNG_DUETETHERNET_FTPRESPONDER_H_ -#define SRC_DUETNG_DUETETHERNET_FTPRESPONDER_H_ - -#include "NetworkResponder.h" - -class FtpResponder : public NetworkResponder -{ -public: - FtpResponder(NetworkResponder *n); - bool Spin() override; // do some work, returning true if we did anything significant - bool Accept(Socket *s, Protocol protocol) override; // ask the responder to accept this connection, returns true if it did - void Terminate(Protocol protocol) override; // terminate the responder if it is serving the specified protocol - - void Diagnostics(MessageType mtype) const override; - -protected: - static const size_t ftpMessageLength = 128; // maximum line length for incoming FTP commands - static const uint32_t ftpPasvPortTimeout = 10000; // maximum time to wait for an FTP data connection in milliseconds - - Socket *dataSocket; - Port passivePort; - uint32_t passivePortOpenTime; - OutputBuffer *dataBuf; - - void ConnectionLost() override; - void SendData() override; - - bool sendError; - void SendPassiveData(); - - void DoUpload(); - - bool ReadData(); - void CharFromClient(char c); - void ProcessLine(); - const char *GetParameter(const char *after) const; // return the parameter followed by whitespaces after a command - void ChangeDirectory(const char *newDirectory); - - void CloseDataPort(); - - bool haveCompleteLine; - char clientMessage[ftpMessageLength]; - size_t clientPointer; - - char currentDirectory[MaxFilenameLength]; - char fileToMove[MaxFilenameLength]; -}; - -#endif /* SRC_DUETNG_DUETETHERNET_FTPRESPONDER_H_ */ diff --git a/src/Network2/HttpResponder.cpp b/src/Network2/HttpResponder.cpp deleted file mode 100644 index 16df8a4e..00000000 --- a/src/Network2/HttpResponder.cpp +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * HttpResponder.cpp - * - * Created on: 14 Apr 2017 - * Author: David - */ - -#include "HttpResponder.h" -#include "GCodes/GCodes.h" -#include "PrintMonitor.h" -#include "Libraries/General/IP4String.h" - -#define KO_START "rr_" -const size_t KoFirst = 3; - -const char* const overflowResponse = "overflow"; -const char* const badEscapeResponse = "bad escape"; - -const uint32_t HttpReceiveTimeout = 2000; - -HttpResponder::HttpResponder(NetworkResponder *n) : NetworkResponder(n) -{ -} - -// Ask the responder to accept this connection, returns true if it did -bool HttpResponder::Accept(Socket *s, Protocol protocol) -{ - if (responderState == ResponderState::free && protocol == HttpProtocol) - { - // Make sure we can get an output buffer before we accept the connection, or we won't be able to reply - if (outBuf != nullptr || OutputBuffer::Allocate(outBuf)) - { - responderState = ResponderState::reading; - skt = s; - timer = millis(); - - // Reset the parse state variables - clientPointer = 0; - parseState = HttpParseState::doingCommandWord; - numCommandWords = 0; - numQualKeys = 0; - numHeaderKeys = 0; - commandWords[0] = clientMessage; - - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("HTTP connection accepted\n"); - } - return true; - } - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("HTTP connection refused (no buffers)\n"); - } - } - return false; -} - -// Do some work, returning true if we did anything significant -bool HttpResponder::Spin() -{ - switch (responderState) - { - case ResponderState::free: - return false; - - case ResponderState::reading: - { - bool readSomething = false; - char c; - while (skt->ReadChar(c)) - { - if (CharFromClient(c)) - { - timer = millis(); // restart the timeout - return true; - } - readSomething = true; - } - - // Here when we were not able to read a character but we didn't receive a finished message - if (readSomething) - { - timer = millis(); // restart the timeout - return true; - } - - if (!skt->CanRead() || millis() - timer >= HttpReceiveTimeout) - { - ConnectionLost(); - return true; - } - - return false; - } - - case ResponderState::gettingFileInfoLock: - if (!fileInfoLock.Acquire(this)) - { - return false; - } - responderState = ResponderState::gettingFileInfo; - // no break - - case ResponderState::gettingFileInfo: - if (SendFileInfo()) - { - fileInfoLock.Release(this); // release the lock - } - return true; - - case ResponderState::uploading: - DoUpload(); - return true; - - case ResponderState::sending: - SendData(); - return true; - - default: // should not happen - return false; - } -} - -// Process a character from the client -// Rewritten as a state machine by dc42 to increase capability and speed, and reduce RAM requirement. -// On entry: -// There is space for at least 1 character in clientMessage. -// On return: -// If we return false: -// We want more characters. There is space for at least 1 character in clientMessage. -// If we return true: -// We have processed the message and sent the reply. No more characters may be read from this message. -// Whenever this calls ProcessMessage: -// The first line has been split up into words. Variables numCommandWords and commandWords give the number of words we found -// and the pointers to each word. The second word is treated specially. It is assumed to be a filename followed by an optional -// qualifier comprising key/value pairs. Both may include %xx escapes, and the qualifier may include + to mean space. We store -// a pointer to the filename without qualifier in commandWords[1]. We store the qualifier key/value pointers in array 'qualifiers' -// and the number of them in numQualKeys. -// The remaining lines have been parsed as header name/value pairs. Pointers to them are stored in array 'headers' and the number -// of them in numHeaders. -// If one of our arrays is about to overflow, or the message is not in a format we expect, then we call RejectMessage with an -// appropriate error code and string. -bool HttpResponder::CharFromClient(char c) -{ - switch (parseState) - { - case HttpParseState::doingCommandWord: - switch(c) - { - case '\n': - clientMessage[clientPointer++] = 0; - ++numCommandWords; - numHeaderKeys = 0; - headers[0].key = clientMessage + clientPointer; - parseState = HttpParseState::doingHeaderKey; - break; - case '\r': - break; - case ' ': - case '\t': - clientMessage[clientPointer++] = 0; - if (numCommandWords < MaxCommandWords) - { - ++numCommandWords; - commandWords[numCommandWords] = clientMessage + clientPointer; - if (numCommandWords == 1) - { - parseState = HttpParseState::doingFilename; - } - } - else - { - RejectMessage("too many command words"); - return true; - } - break; - default: - clientMessage[clientPointer++] = c; - break; - } - break; - - case HttpParseState::doingFilename: - switch(c) - { - case '\n': - clientMessage[clientPointer++] = 0; - ++numCommandWords; - numQualKeys = 0; - numHeaderKeys = 0; - headers[0].key = clientMessage + clientPointer; - parseState = HttpParseState::doingHeaderKey; - break; - case '?': - clientMessage[clientPointer++] = 0; - ++numCommandWords; - numQualKeys = 0; - qualifiers[0].key = clientMessage + clientPointer; - parseState = HttpParseState::doingQualifierKey; - break; - case '%': - parseState = HttpParseState::doingFilenameEsc1; - break; - case '\r': - break; - case ' ': - case '\t': - clientMessage[clientPointer++] = 0; - if (numCommandWords < MaxCommandWords) - { - ++numCommandWords; - commandWords[numCommandWords] = clientMessage + clientPointer; - parseState = HttpParseState::doingCommandWord; - } - else - { - RejectMessage("too many command words"); - return true; - } - break; - default: - clientMessage[clientPointer++] = c; - break; - } - break; - - case HttpParseState::doingQualifierKey: - switch(c) - { - case '=': - clientMessage[clientPointer++] = 0; - qualifiers[numQualKeys].value = clientMessage + clientPointer; - ++numQualKeys; - parseState = HttpParseState::doingQualifierValue; - break; - case '\n': // key with no value - case ' ': - case '\t': - case '\r': - case '%': // none of our keys needs escaping, so treat an escape within a key as an error - case '&': // key with no value - RejectMessage("bad qualifier key"); - return true; - default: - clientMessage[clientPointer++] = c; - break; - } - break; - - case HttpParseState::doingQualifierValue: - switch(c) - { - case '\n': - clientMessage[clientPointer++] = 0; - qualifiers[numQualKeys].key = clientMessage + clientPointer; // so that we can read the whole value even if it contains a null - numHeaderKeys = 0; - headers[0].key = clientMessage + clientPointer; - parseState = HttpParseState::doingHeaderKey; - break; - case ' ': - case '\t': - clientMessage[clientPointer++] = 0; - qualifiers[numQualKeys].key = clientMessage + clientPointer; // so that we can read the whole value even if it contains a null - commandWords[numCommandWords] = clientMessage + clientPointer; - parseState = HttpParseState::doingCommandWord; - break; - case '\r': - break; - case '%': - parseState = HttpParseState::doingQualifierValueEsc1; - break; - case '&': - // Another variable is coming - clientMessage[clientPointer++] = 0; - qualifiers[numQualKeys].key = clientMessage + clientPointer; // so that we can read the whole value even if it contains a null - if (numQualKeys < MaxQualKeys) - { - parseState = HttpParseState::doingQualifierKey; - } - else - { - RejectMessage("too many keys in qualifier"); - return true; - } - break; - case '+': - clientMessage[clientPointer++] = ' '; - break; - default: - clientMessage[clientPointer++] = c; - break; - } - break; - - case HttpParseState::doingFilenameEsc1: - case HttpParseState::doingQualifierValueEsc1: - if (c >= '0' && c <= '9') - { - decodeChar = (c - '0') << 4; - parseState = (HttpParseState)((int)parseState + 1); - } - else if (c >= 'A' && c <= 'F') - { - decodeChar = (c - ('A' - 10)) << 4; - parseState = (HttpParseState)((int)parseState + 1); - } - else - { - RejectMessage(badEscapeResponse); - return true; - } - break; - - case HttpParseState::doingFilenameEsc2: - case HttpParseState::doingQualifierValueEsc2: - if (c >= '0' && c <= '9') - { - clientMessage[clientPointer++] = decodeChar | (c - '0'); - parseState = (HttpParseState)((int)parseState - 2); - } - else if (c >= 'A' && c <= 'F') - { - clientMessage[clientPointer++] = decodeChar | (c - ('A' - 10)); - parseState = (HttpParseState)((int)parseState - 2); - } - else - { - RejectMessage(badEscapeResponse); - return true; - } - break; - - case HttpParseState::doingHeaderKey: - switch(c) - { - case '\n': - if (clientMessage + clientPointer == headers[numHeaderKeys].key) // if the key hasn't started yet, then this is the blank line at the end - { - ProcessMessage(); - return true; - } - else - { - RejectMessage("unexpected newline"); - return true; - } - break; - case '\r': - break; - case ':': - if (numHeaderKeys == MaxHeaders - 1) - { - RejectMessage("too many header key-value pairs"); - return true; - } - clientMessage[clientPointer++] = 0; - headers[numHeaderKeys].value = clientMessage + clientPointer; - ++numHeaderKeys; - parseState = HttpParseState::expectingHeaderValue; - break; - default: - clientMessage[clientPointer++] = c; - break; - } - break; - - case HttpParseState::expectingHeaderValue: - if (c == ' ' || c == '\t') - { - break; // ignore spaces between header key and value - } - parseState = HttpParseState::doingHeaderValue; - // no break - - case HttpParseState::doingHeaderValue: - if (c == '\n') - { - parseState = HttpParseState::doingHeaderContinuation; - } - else if (c != '\r') - { - clientMessage[clientPointer++] = c; - } - break; - - case HttpParseState::doingHeaderContinuation: - switch(c) - { - case ' ': - case '\t': - // It's a continuation of the previous value - clientMessage[clientPointer++] = c; - parseState = HttpParseState::doingHeaderValue; - break; - case '\n': - // It's the blank line - clientMessage[clientPointer] = 0; - ProcessMessage(); - return true; - case '\r': - break; - default: - // It's a new key - if (clientPointer + 3 <= ARRAY_SIZE(clientMessage)) - { - clientMessage[clientPointer++] = 0; - headers[numHeaderKeys].key = clientMessage + clientPointer; - clientMessage[clientPointer++] = c; - parseState = HttpParseState::doingHeaderKey; - } - else - { - RejectMessage(overflowResponse); - return true; - } - break; - } - break; - - default: - break; - } - - if (clientPointer == ARRAY_SIZE(clientMessage)) - { - RejectMessage(overflowResponse); - return true; - } - return false; -} - -// Get the Json response for this command. -// 'value' is null-terminated, but we also pass its length in case it contains embedded nulls, which matters when uploading files. -// Return true if we generated a json response to send, false if we didn't and changed the state instead -bool HttpResponder::GetJsonResponse(const char* request, OutputBuffer *&response, bool& keepOpen) -{ - keepOpen = false; // assume we don't want to persist the connection - if (StringEquals(request, "connect") && GetKeyValue("password") != nullptr) - { - if (!CheckAuthenticated()) - { - if (!reprap.CheckPassword(GetKeyValue("password"))) - { - // Wrong password - response->copy("{\"err\":1}"); - reprap.GetPlatform().MessageF(LogMessage, "HTTP client %s attempted login with incorrect password\n", IP4String(GetRemoteIP()).c_str()); - return true; - } - if (!Authenticate()) - { - // No more HTTP sessions available - response->copy("{\"err\":2}"); - reprap.GetPlatform().MessageF(LogMessage, "HTTP client %s attempted login but no more sessions available\n", IP4String(GetRemoteIP()).c_str()); - return true; - } - } - - // Client has been logged in - response->printf("{\"err\":0,\"sessionTimeout\":%" PRIu32 ",\"boardType\":\"%s\"}", HttpSessionTimeout, GetPlatform().GetBoardString()); - reprap.GetPlatform().MessageF(LogMessage, "HTTP client %s login succeeded\n", IP4String(GetRemoteIP()).c_str()); - - // See if we can update the current RTC date and time - const char* const timeString = GetKeyValue("time"); - if (timeString != nullptr && !GetPlatform().IsDateTimeSet()) - { - struct tm timeInfo; - memset(&timeInfo, 0, sizeof(timeInfo)); - if (strptime(timeString, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr) - { - GetPlatform().SetDateTime(mktime(&timeInfo)); - } - } - } - else if (!CheckAuthenticated()) - { - RejectMessage("Not authorized", 500); - return false; - } - else if (StringEquals(request, "disconnect")) - { - response->printf("{\"err\":%d}", (RemoveAuthentication()) ? 0 : 1); - reprap.GetPlatform().MessageF(LogMessage, "HTTP client %s disconnected\n", IP4String(GetRemoteIP()).c_str()); - } - else if (StringEquals(request, "status")) - { - int type = 0; - if (GetKeyValue("type") != nullptr) - { - // New-style JSON status responses - type = atoi(GetKeyValue("type")); - if (type < 1 || type > 3) - { - type = 1; - } - - OutputBuffer::Release(response); - response = reprap.GetStatusResponse(type, ResponseSource::HTTP); - } - else - { - // Deprecated - OutputBuffer::Release(response); - response = reprap.GetLegacyStatusResponse(1, 0); - } - } - else if (StringEquals(request, "gcode") && GetKeyValue("gcode") != nullptr) - { - RegularGCodeInput * const httpInput = reprap.GetGCodes().GetHTTPInput(); - httpInput->Put(HttpMessage, GetKeyValue("gcode")); - response->printf("{\"buff\":%u}", httpInput->BufferSpaceLeft()); - } - else if (StringEquals(request, "upload")) - { - response->printf("{\"err\":%d}", (uploadError) ? 1 : 0); - } - else if (StringEquals(request, "delete") && GetKeyValue("name") != nullptr) - { - const bool ok = GetPlatform().GetMassStorage()->Delete(FS_PREFIX, GetKeyValue("name")); - response->printf("{\"err\":%d}", (ok) ? 0 : 1); - } - else if (StringEquals(request, "filelist") && GetKeyValue("dir") != nullptr) - { - OutputBuffer::Release(response); - response = reprap.GetFilelistResponse(GetKeyValue("dir")); - } - else if (StringEquals(request, "files")) - { - const char* dir = GetKeyValue("dir"); - if (dir == nullptr) - { - dir = GetPlatform().GetGCodeDir(); - } - const char* const flagDirsVal = GetKeyValue("flagDirs"); - const bool flagDirs = flagDirsVal != nullptr && atoi(flagDirsVal) == 1; - OutputBuffer::Release(response); - response = reprap.GetFilesResponse(dir, flagDirs); - } - else if (StringEquals(request, "fileinfo")) - { - const char* const nameVal = GetKeyValue("name"); - if (nameVal != nullptr) - { - // Regular rr_fileinfo?name=xxx call - SafeStrncpy(filenameBeingProcessed, nameVal, ARRAY_SIZE(filenameBeingProcessed)); - } - else - { - // Simple rr_fileinfo call to get info about the file being printed - filenameBeingProcessed[0] = 0; - } - responderState = ResponderState::gettingFileInfoLock; - return false; - } - else if (StringEquals(request, "move")) - { - const char* const oldVal = GetKeyValue("old"); - const char* const newVal = GetKeyValue("new"); - bool success = false; - if (oldVal != nullptr && newVal != nullptr) - { - MassStorage * const ms = GetPlatform().GetMassStorage(); - if (StringEquals(GetKeyValue("deleteexisting"), "yes") && ms->FileExists(oldVal) && ms->FileExists(newVal)) - { - ms->Delete(nullptr, newVal, true); - } - success = ms->Rename(oldVal, newVal); - } - response->printf("{\"err\":%d}", (success) ? 0 : 1); - } - else if (StringEquals(request, "mkdir")) - { - const char* const dirVal = GetKeyValue("dir"); - bool success = false; - if (dirVal != nullptr) - { - success = GetPlatform().GetMassStorage()->MakeDirectory(dirVal); - } - response->printf("{\"err\":%d}", (success) ? 0 : 1); - } - else if (StringEquals(request, "config")) - { - OutputBuffer::Release(response); - response = reprap.GetConfigResponse(); - } - else - { - RejectMessage("Unknown request", 500); - return false; - } - return true; -} - -const char* HttpResponder::GetKeyValue(const char *key) const -{ - for (size_t i = 0; i < numQualKeys; ++i) - { - if (StringEquals(qualifiers[i].key, key)) - { - return qualifiers[i].value; - } - } - return nullptr; -} - -// Called to process a FileInfo request, which may take several calls -// When we have finished, set the state back to free. -bool HttpResponder::SendFileInfo() -{ - OutputBuffer *jsonResponse = nullptr; - const bool gotFileInfo = reprap.GetPrintMonitor().GetFileInfoResponse(filenameBeingProcessed, jsonResponse); - if (gotFileInfo) - { - // Got it - send the response now - outBuf->copy( "HTTP/1.1 200 OK\n" - "Cache-Control: no-cache, no-store, must-revalidate\n" - "Pragma: no-cache\n" - "Expires: 0\n" - "Access-Control-Allow-Origin: *\n" - "Content-Type: application/json\n" - ); - outBuf->catf("Content-Length: %u\n", (jsonResponse != nullptr) ? jsonResponse->Length() : 0); - outBuf->cat("Connection: close\n\n"); - outBuf->Append(jsonResponse); - Commit(); - } - return gotFileInfo; -} - -// Authenticate current IP and return true on success -bool HttpResponder::Authenticate() -{ - if (CheckAuthenticated()) - { - return true; - } - - if (numSessions < MaxHttpSessions) - { - sessions[numSessions].ip = GetRemoteIP(); - sessions[numSessions].lastQueryTime = millis(); - sessions[numSessions].isPostUploading = false; - numSessions++; - return true; - } - return false; -} - -// Check and update the authentication -bool HttpResponder::CheckAuthenticated() -{ - const uint32_t remoteIP = GetRemoteIP(); - for (size_t i = 0; i < numSessions; i++) - { - if (sessions[i].ip == remoteIP) - { - sessions[i].lastQueryTime = millis(); - return true; - } - } - return false; -} - -bool HttpResponder::RemoveAuthentication() -{ - const uint32_t remoteIP = skt->GetRemoteIP(); - for (size_t i = numSessions; i != 0; ) - { - --i; - if (sessions[i].ip == remoteIP) - { - if (sessions[i].isPostUploading) - { - // Don't allow sessions with active POST uploads to be removed - return false; - } - - for (size_t k = i + 1; k < numSessions; ++k) - { - memcpy(&sessions[k - 1], &sessions[k], sizeof(HttpSession)); - } - numSessions--; - return true; - } - } - return false; -} - -void HttpResponder::SendFile(const char* nameOfFileToSend, bool isWebFile) -{ - FileStore *fileToSend = nullptr; - bool zip = false; - - if (isWebFile) - { - if (nameOfFileToSend[0] == '/') - { - ++nameOfFileToSend; // all web files are relative to the /www folder, so remove the leading '/' - if (nameOfFileToSend[0] == 0) - { - nameOfFileToSend = INDEX_PAGE_FILE; - } - } - - // Try to open a gzipped version of the file first - if (!StringEndsWith(nameOfFileToSend, ".gz") && strlen(nameOfFileToSend) + 3 <= MaxFilenameLength) - { - String<MaxFilenameLength> nameBuf; - nameBuf.copy(nameOfFileToSend); - nameBuf.cat(".gz"); - fileToSend = GetPlatform().OpenFile(GetPlatform().GetWebDir(), nameBuf.c_str(), OpenMode::read); - if (fileToSend != nullptr) - { - zip = true; - } - } - - // If that failed, try to open the normal version of the file - if (fileToSend == nullptr) - { - fileToSend = GetPlatform().OpenFile(GetPlatform().GetWebDir(), nameOfFileToSend, OpenMode::read); - } - - // If we still couldn't find the file and it was an HTML file, return the 404 error page - if (fileToSend == nullptr && (StringEndsWith(nameOfFileToSend, ".html") || StringEndsWith(nameOfFileToSend, ".htm"))) - { - nameOfFileToSend = FOUR04_PAGE_FILE; - fileToSend = GetPlatform().OpenFile(GetPlatform().GetWebDir(), nameOfFileToSend, OpenMode::read); - } - - if (fileToSend == nullptr) - { - RejectMessage("not found", 404); - return; - } - fileBeingSent = fileToSend; - } - else - { - fileToSend = GetPlatform().OpenFile(FS_PREFIX, nameOfFileToSend, OpenMode::read); - if (fileToSend == nullptr) - { - RejectMessage("not found", 404); - return; - } - fileBeingSent = fileToSend; - } - - outBuf->copy("HTTP/1.1 200 OK\n"); - - // Don't cache files served by rr_download - if (!isWebFile) - { - outBuf->cat( "Cache-Control: no-cache, no-store, must-revalidate\n" - "Pragma: no-cache\n" - "Expires: 0\n" - "Access-Control-Allow-Origin: *\n" - ); - } - - const char* contentType; - if (StringEndsWith(nameOfFileToSend, ".png")) - { - contentType = "image/png"; - } - else if (StringEndsWith(nameOfFileToSend, ".ico")) - { - contentType = "image/x-icon"; - } - else if (StringEndsWith(nameOfFileToSend, ".js")) - { - contentType = "application/javascript"; - } - else if (StringEndsWith(nameOfFileToSend, ".css")) - { - contentType = "text/css"; - } - else if (StringEndsWith(nameOfFileToSend, ".htm") || StringEndsWith(nameOfFileToSend, ".html")) - { - contentType = "text/html"; - } - else if (StringEndsWith(nameOfFileToSend, ".zip")) - { - contentType = "application/zip"; - zip = true; - } - else if (StringEndsWith(nameOfFileToSend, ".g") || StringEndsWith(nameOfFileToSend, ".gc") || StringEndsWith(nameOfFileToSend, ".gcode")) - { - contentType = "text/plain"; - } - else - { - contentType = "application/octet-stream"; - } - outBuf->catf("Content-Type: %s\n", contentType); - - if (zip && fileToSend != nullptr) - { - outBuf->cat("Content-Encoding: gzip\n"); - outBuf->catf("Content-Length: %lu\n", fileToSend->Length()); - } - - outBuf->cat("Connection: close\n\n"); - Commit(); -} - -void HttpResponder::SendGCodeReply() -{ - // Do we need to keep the G-Code reply for other clients? - bool clearReply = false; - if (!gcodeReply->IsEmpty()) - { - clientsServed++; - if (clientsServed < numSessions) - { - // Yes - make sure the Network class doesn't discard its buffers yet - // NB: This must happen here, because NetworkTransaction::Write() might already release OutputBuffers - gcodeReply->IncreaseReferences(1); - } - else - { - // No - clean up again later - clearReply = true; - } - - if (reprap.Debug(moduleWebserver)) - { - GetPlatform().MessageF(UsbMessage, "Sending G-Code reply to client %d of %d (length %u)\n", clientsServed, numSessions, gcodeReply->DataLength()); - } - } - - // Send the whole G-Code reply as plain text to the client - outBuf->copy( "HTTP/1.1 200 OK\n" - "Cache-Control: no-cache, no-store, must-revalidate\n" - "Pragma: no-cache\n" - "Expires: 0\n" - "Access-Control-Allow-Origin: *\n" - "Content-Type: text/plain\n" - ); - outBuf->catf("Content-Length: %u\n", gcodeReply->DataLength()); - outBuf->cat("Connection: close\n\n"); - outStack->Append(gcodeReply); - Commit(); - - // Possibly clean up the G-code reply once again - if (clearReply) - { - gcodeReply->Clear(); - } -} - -void HttpResponder::SendJsonResponse(const char* command) -{ - // Try to authorise the user automatically to retain compatibility with the old web interface - if (!CheckAuthenticated() && reprap.NoPasswordSet()) - { - Authenticate(); - } - - // Update the authentication status and try handle "text/plain" requests here - if (CheckAuthenticated()) - { - if (StringEquals(command, "reply")) // rr_reply - { - SendGCodeReply(); - return; - } - - if (StringEquals(command, "configfile")) // rr_configfile [DEPRECATED] - { - const char *configPath = GetPlatform().GetMassStorage()->CombineName(GetPlatform().GetSysDir(), GetPlatform().GetConfigFile()); - char fileName[MaxFilenameLength]; - SafeStrncpy(fileName, configPath, ARRAY_SIZE(fileName)); - SendFile(fileName, false); - return; - } - - if (StringEquals(command, "download")) - { - const char* const filename = GetKeyValue("name"); - if (filename != nullptr) - { - SendFile(filename, false); - return; - } - } - } - - // Try to process a request for JSON responses - OutputBuffer *jsonResponse; - if (!OutputBuffer::Allocate(jsonResponse)) - { - // Reset the connection immediately if we cannot write any data. Should never happen. - skt->Terminate(); - return; - } - - bool mayKeepOpen; - const bool gotResponse = GetJsonResponse(command, jsonResponse, mayKeepOpen); - if (!gotResponse) - { - // Either this request was rejected, or it will take longer to process e.g. rr_fileinfo - OutputBuffer::Release(jsonResponse); - return; - } - - // Send the JSON response - bool keepOpen = false; - if (mayKeepOpen) - { - // Check that the browser wants to persist the connection too - for (size_t i = 0; i < numHeaderKeys; ++i) - { - if (StringEquals(headers[i].key, "Connection")) - { - // Comment out the following line to disable persistent connections - keepOpen = StringEquals(headers[i].value, "keep-alive"); - break; - } - } - } - - outBuf->copy( "HTTP/1.1 200 OK\n" - "Cache-Control: no-cache, no-store, must-revalidate\n" - "Pragma: no-cache\n" - "Expires: 0\n" - "Access-Control-Allow-Origin: *\n" - "Content-Type: application/json\n" - ); - outBuf->catf("Content-Length: %u\n", (jsonResponse != nullptr) ? jsonResponse->Length() : 0); - outBuf->catf("Connection: %s\n\n", keepOpen ? "keep-alive" : "close"); - outBuf->Append(jsonResponse); - - Commit(keepOpen ? ResponderState::reading : ResponderState::free); -} - -// Process the message received so far. We have reached the end of the headers. -// Return true if the message is complete, false if we want to continue receiving data (i.e. postdata) -void HttpResponder::ProcessMessage() -{ - if (reprap.Debug(moduleWebserver)) - { - GetPlatform().MessageF(UsbMessage, "HTTP req, command words {"); - for (size_t i = 0; i < numCommandWords; ++i) - { - GetPlatform().MessageF(UsbMessage, " %s", commandWords[i]); - } - GetPlatform().Message(UsbMessage, " }, parameters {"); - - for (size_t i = 0; i < numQualKeys; ++i) - { - GetPlatform().MessageF(UsbMessage, " %s=%s", qualifiers[i].key, qualifiers[i].value); - } - GetPlatform().Message(UsbMessage, " }\n"); - } - - if (numCommandWords < 2) - { - RejectMessage("too few command words"); - return; - } - - if (StringEquals(commandWords[0], "GET")) - { - if (StringStartsWith(commandWords[1], KO_START)) - { - SendJsonResponse(commandWords[1] + KoFirst); - } - else if (commandWords[1][0] == '/' && StringStartsWith(commandWords[1] + 1, KO_START)) - { - SendJsonResponse(commandWords[1] + 1 + KoFirst); - } - else - { - SendFile(commandWords[1], true); - } - return; - } - - if (StringEquals(commandWords[0], "OPTIONS")) - { - outBuf->copy( "HTTP/1.1 200 OK\n" - "Allow: OPTIONS, GET, POST\n" - "Cache-Control: no-cache, no-store, must-revalidate\n" - "Pragma: no-cache\n" - "Expires: 0\n" - "Access-Control-Allow-Origin: *\n" - "Access-Control-Allow-Headers: Content-Type\n" - "Content-Length: 0\n" - "\n" - ); - Commit(); - return; - } - - if (CheckAuthenticated() && StringEquals(commandWords[0], "POST")) - { - const bool isUploadRequest = (StringEquals(commandWords[1], KO_START "upload")) - || (commandWords[1][0] == '/' && StringEquals(commandWords[1] + 1, KO_START "upload")); - if (isUploadRequest) - { - const char* const filename = GetKeyValue("name"); - if (filename != nullptr) - { - // See how many bytes we expect to read - bool contentLengthFound = false; - for (size_t i = 0; i < numHeaderKeys; i++) - { - if (StringEquals(headers[i].key, "Content-Length")) - { - postFileLength = atoi(headers[i].value); - contentLengthFound = true; - break; - } - } - - // Start POST file upload - if (!contentLengthFound) - { - RejectMessage("invalid POST upload request"); - return; - } - - // Start a new file upload - FileStore *file = GetPlatform().OpenFile(FS_PREFIX, filename, OpenMode::write); - if (file == nullptr) - { - RejectMessage("could not create file"); - return; - - } - StartUpload(file, filename); - - // Try to get the last modified file date and time - const char* const lastModifiedString = GetKeyValue("time"); - if (lastModifiedString != nullptr) - { - struct tm timeInfo; - memset(&timeInfo, 0, sizeof(timeInfo)); - if (strptime(lastModifiedString, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr) - { - fileLastModified = mktime(&timeInfo); - } - else - { - fileLastModified = 0; - } - } - else - { - fileLastModified = 0; - } - - if (reprap.Debug(moduleWebserver)) - { - GetPlatform().MessageF(UsbMessage, "Start uploading file %s length %lu\n", filename, postFileLength); - } - uploadedBytes = 0; - - // Keep track of the connection that is now uploading - const uint32_t remoteIP = GetRemoteIP(); - const uint16_t remotePort = skt->GetRemotePort(); - for(size_t i = 0; i < numSessions; i++) - { - if (sessions[i].ip == remoteIP) - { - sessions[i].postPort = remotePort; - sessions[i].isPostUploading = true; - break; - } - } - return; - } - } - RejectMessage("only rr_upload is supported for POST requests"); - } - else - { - RejectMessage("Unknown message type or not authenticated"); - } -} - -// Reject the current message -void HttpResponder::RejectMessage(const char* response, unsigned int code) -{ - if (reprap.Debug(moduleWebserver)) - { - GetPlatform().MessageF(UsbMessage, "Webserver: rejecting message with: %u %s\n", code, response); - } - outBuf->printf("HTTP/1.1 %u %s\nConnection: close\n\n", code, response); - Commit(); -} - -// This function overrides the one in class NetworkResponder. -// It tries to process a chunk of uploaded data and changes the state if finished. -void HttpResponder::DoUpload() -{ - const uint8_t *buffer; - size_t len; - if (skt->ReadBuffer(buffer, len)) - { - skt->Taken(len); - uploadedBytes += len; - - if (!fileBeingUploaded.Write(buffer, len)) - { - uploadError = true; - GetPlatform().Message(ErrorMessage, "Could not write upload data!\n"); - CancelUpload(); - SendJsonResponse("upload"); - return; - } - } - - // See if the upload has finished - if (uploadedBytes >= postFileLength) - { - // Reset POST upload state for this client - const uint32_t remoteIP = GetRemoteIP(); - for (size_t i = 0; i < numSessions; i++) - { - if (sessions[i].ip == remoteIP && sessions[i].isPostUploading) - { - sessions[i].isPostUploading = false; - sessions[i].lastQueryTime = millis(); - break; - } - } - - FinishUpload(postFileLength, fileLastModified); - SendJsonResponse("upload"); - return; - } - else if (!skt->CanRead()) - { - // We cannot read any more, discard the transaction - ConnectionLost(); - } -} - -// This is called to force termination if we implement the specified protocol -void HttpResponder::Terminate(Protocol protocol) -{ - if (responderState != ResponderState::free && (protocol == HttpProtocol || protocol == AnyProtocol)) - { - ConnectionLost(); - } -} - -// This overrides the version in class NetworkResponder -void HttpResponder::ConnectionLost() -{ - fileInfoLock.Release(this); - NetworkResponder::ConnectionLost(); -} - -// This overrides the version in class NetworkResponder -void HttpResponder::CancelUpload() -{ - if (skt != nullptr) - { - for (size_t i = 0; i < numSessions; i++) - { - if (sessions[i].ip == skt->GetRemoteIP() && sessions[i].isPostUploading) - { - sessions[i].isPostUploading = false; - sessions[i].lastQueryTime = millis(); - break; - } - } - } - NetworkResponder::CancelUpload(); -} - -// This overrides the version in class NetworkResponder -void HttpResponder::SendData() -{ - NetworkResponder::SendData(); - if (responderState == ResponderState::reading) - { - timer = millis(); // restart the timer - } -} - -void HttpResponder::Diagnostics(MessageType mt) const -{ - GetPlatform().MessageF(mt, " HTTP(%d)", (int)responderState); -} - -/*static*/ void HttpResponder::HandleGCodeReply(const char *reply) -{ - if (numSessions > 0) - { - OutputBuffer *buffer = gcodeReply->GetLastItem(); - if (buffer == nullptr || buffer->IsReferenced()) - { - if (!OutputBuffer::Allocate(buffer)) - { - // No more space available, stop here - return; - } - gcodeReply->Push(buffer); - } - - buffer->cat(reply); - clientsServed = 0; - seq++; - } -} - -/*static*/ void HttpResponder::HandleGCodeReply(OutputBuffer *reply) -{ - if (reply != nullptr) - { - if (numSessions > 0) - { - // FIXME: This might cause G-code responses to be sent twice to fast HTTP clients, but - // I (chrishamm) cannot think of a nicer way to deal with slow clients at the moment... - gcodeReply->Push(reply); - clientsServed = 0; - seq++; - } - else - { - // Don't use buffers that may never get released... - OutputBuffer::ReleaseAll(reply); - } - } -} - - -/*static*/ void HttpResponder::CheckSessions() -{ - const uint32_t now = millis(); - for (size_t i = numSessions; i != 0; ) - { - --i; - if ((now - sessions[i].lastQueryTime) > HttpSessionTimeout) - { - // Check for timed out sessions - for (size_t k = i + 1; k < numSessions; k++) - { - memcpy(&sessions[k - 1], &sessions[k], sizeof(HttpSession)); - } - numSessions--; - clientsServed++; // assume the disconnected client hasn't fetched the G-Code reply yet - } - } - - // If we cannot send the G-Code reply to anyone, we may free up some run-time space by dumping it - if (numSessions == 0 || clientsServed >= numSessions) - { - while (!gcodeReply->IsEmpty()) - { - OutputBuffer::ReleaseAll(gcodeReply->Pop()); - } - clientsServed = 0; - } -} - -/*static*/ void HttpResponder::CommonDiagnostics(MessageType mtype) -{ - GetPlatform().MessageF(mtype, "HTTP sessions: %u of %u\n", numSessions, MaxHttpSessions); -} - -// Static data - -HttpResponder::HttpSession HttpResponder::sessions[MaxHttpSessions]; -unsigned int HttpResponder::numSessions = 0; -unsigned int HttpResponder::clientsServed = 0; - -uint32_t HttpResponder::seq = 0; -OutputStack *HttpResponder::gcodeReply = new OutputStack(); - -NetworkResponderLock HttpResponder::fileInfoLock; - -// End diff --git a/src/Network2/HttpResponder.h b/src/Network2/HttpResponder.h deleted file mode 100644 index b2369d22..00000000 --- a/src/Network2/HttpResponder.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * HttpResponder.h - * - * Created on: 14 Apr 2017 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_HTTPRESPONDER_H_ -#define SRC_DUETNG_DUETETHERNET_HTTPRESPONDER_H_ - -#include "NetworkResponder.h" - -class HttpResponder : public NetworkResponder -{ -public: - HttpResponder(NetworkResponder *n); - bool Spin() override; // do some work, returning true if we did anything significant - bool Accept(Socket *s, Protocol protocol) override; // ask the responder to accept this connection, returns true if it did - void Terminate(Protocol protocol) override; // terminate the responder if it is serving the specified protocol - void Diagnostics(MessageType mtype) const override; - - static void HandleGCodeReply(const char *reply); - static void HandleGCodeReply(OutputBuffer *reply); - static uint32_t GetReplySeq() { return seq; } - static void CheckSessions(); - static void CommonDiagnostics(MessageType mtype); - -protected: - void ConnectionLost() override; - void CancelUpload() override; - void SendData() override; - -private: - static const size_t MaxHttpSessions = 8; // maximum number of simultaneous HTTP sessions - static const uint16_t WebMessageLength = TCP_MSS; // maximum length of the web message we accept after decoding - static const size_t MaxCommandWords = 4; // max number of space-separated words in the command - static const size_t MaxQualKeys = 5; // max number of key/value pairs in the qualifier - static const size_t MaxHeaders = 30; // max number of key/value pairs in the headers - static const uint32_t HttpSessionTimeout = 8000; // HTTP session timeout in milliseconds - - enum class HttpParseState - { - doingCommandWord, // receiving a word in the first line of the HTTP request - doingFilename, // receiving the filename (second word in the command line) - doingFilenameEsc1, // received '%' in the filename (e.g. we are being asked for a filename with spaces in it) - doingFilenameEsc2, // received '%' and one hex digit in the filename - doingQualifierKey, // receiving a key name in the HTTP request - doingQualifierValue, // receiving a key value in the HTTP request - doingQualifierValueEsc1, // received '%' in the qualifier - doingQualifierValueEsc2, // received '%' and one hex digit in the qualifier - doingHeaderKey, // receiving a header key - expectingHeaderValue, // expecting a header value - doingHeaderValue, // receiving a header value - doingHeaderContinuation // received a newline after a header value - }; - - struct KeyValueIndices - { - const char* key; - const char* value; - }; - - // HTTP sessions - struct HttpSession - { - uint32_t ip; - uint32_t lastQueryTime; - bool isPostUploading; - uint16_t postPort; - }; - - bool Authenticate(); - bool CheckAuthenticated(); - bool RemoveAuthentication(); - - bool CharFromClient(char c); - void SendFile(const char* nameOfFileToSend, bool isWebFile); - void SendGCodeReply(); - void SendJsonResponse(const char* command); - bool GetJsonResponse(const char* request, OutputBuffer *&response, bool& keepOpen); - void ProcessMessage(); - void RejectMessage(const char* s, unsigned int code = 500); - bool SendFileInfo(); - - void DoUpload(); - - const char* GetKeyValue(const char *key) const; // return the value of the specified key, or nullptr if not present - - HttpParseState parseState; - - // Buffers for processing HTTP input - char clientMessage[WebMessageLength + 3]; // holds the command, qualifier, and headers - size_t clientPointer; // current index into clientMessage - char decodeChar; // the character we are decoding in a URL-encoded argument - - // Parser state - const char* commandWords[MaxCommandWords]; - KeyValueIndices qualifiers[MaxQualKeys + 1]; // offsets into clientQualifier of the key/value pairs, the +1 is needed so that values can contain nulls - KeyValueIndices headers[MaxHeaders]; // offsets into clientHeader of the key/value pairs - size_t numCommandWords; - size_t numQualKeys; // number of qualifier keys we have found, <= maxQualKeys - size_t numHeaderKeys; // number of keys we have found, <= maxHeaders - - // rr_fileinfo requests - char filenameBeingProcessed[MaxFilenameLength]; // The filename being processed (for rr_fileinfo) - - // Keeping track of HTTP sessions - static HttpSession sessions[MaxHttpSessions]; - static unsigned int numSessions; - static unsigned int clientsServed; - - // Responses from GCodes class - static uint32_t seq; // Sequence number for G-Code replies - static OutputStack *gcodeReply; - - static NetworkResponderLock fileInfoLock; // PrintMonitor::GetFileInfoResponse is single threaded at present, so use this to control access -}; - -#endif /* SRC_DUETNG_DUETETHERNET_HTTPRESPONDER_H_ */ diff --git a/src/Network2/NetworkBuffer.cpp b/src/Network2/NetworkBuffer.cpp deleted file mode 100644 index 12d924d9..00000000 --- a/src/Network2/NetworkBuffer.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * NetworkBuffer.cpp - * - * Created on: 24 Dec 2016 - * Author: David - */ - -#include "NetworkBuffer.h" - -#include "Storage/FileStore.h" - -NetworkBuffer *NetworkBuffer::freelist = nullptr; - -NetworkBuffer::NetworkBuffer(NetworkBuffer *n) : next(n), dataLength(0), readPointer(0) -{ -} - -// Release this buffer and return the next one in the chain -NetworkBuffer *NetworkBuffer::Release() -{ - NetworkBuffer *ret = next; - next = freelist; - freelist = this; - return ret; -} - -// Read 1 character, returning true if successful, false if no data left -bool NetworkBuffer::ReadChar(char& b) -{ - if (readPointer < dataLength) - { - b = Data()[readPointer++]; - return true; - } - - b = 0; - return false; -} - -// Return the amount of data available, including continuation buffers -size_t NetworkBuffer::TotalRemaining() const -{ - const NetworkBuffer *b = this; - size_t ret = 0; - 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; -} - -// Find the last buffer in a list -/*static*/ NetworkBuffer *NetworkBuffer::FindLast(NetworkBuffer *list) -{ - if (list != nullptr) - { - while (list->next != nullptr) - { - list = list->next; - } - } - return list; -} - -/*static*/ NetworkBuffer *NetworkBuffer::Allocate() -{ - NetworkBuffer *ret = freelist; - if (ret != nullptr) - { - freelist = ret->next; - ret->next = nullptr; - ret->dataLength = ret->readPointer = 0; - } - return ret; -} - -/*static*/ void NetworkBuffer::AllocateBuffers(unsigned int number) -{ - while (number != 0) - { - freelist = new NetworkBuffer(freelist); - --number; - } -} - -// Count how many buffers there are in a chain -/*static*/ unsigned int NetworkBuffer::Count(NetworkBuffer*& ptr) -{ - unsigned int ret = 0; - for (NetworkBuffer *n = ptr; n != nullptr; n = n->next) - { - ++ret; - } - return ret; -} - -// End diff --git a/src/Network2/NetworkBuffer.h b/src/Network2/NetworkBuffer.h deleted file mode 100644 index 306e8a22..00000000 --- a/src/Network2/NetworkBuffer.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * NetworkBuffer.h - * - * Created on: 24 Dec 2016 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_NETWORKBUFFER_H_ -#define SRC_DUETNG_DUETETHERNET_NETWORKBUFFER_H_ - -#include "RepRapFirmware.h" -#include "NetworkDefs.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 -{ -public: - friend class Socket; - - // Release this buffer and return the next one in the chain - NetworkBuffer *Release(); - - // Read 1 character, returning true of successful, false if no data left - bool ReadChar(char& b); - - const uint8_t* UnreadData() const { return Data() + readPointer; } - - // Return the amount of data available, not including continuation buffers - size_t Remaining() const { return dataLength - readPointer; } - - // 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; } - - // Mark some data as taken - void Taken(size_t amount) { readPointer += amount; } - - // Return the length available for writing - size_t SpaceLeft() const { return bufferSize - dataLength; } - - // Return a pointer to the space available for writing - uint8_t* UnwrittenData() { return Data() + 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); - - // Find the last buffer in a list - static NetworkBuffer *FindLast(NetworkBuffer *list); - - // Allocate a buffer - static NetworkBuffer *Allocate(); - - // Alocate buffers and put them in the freelist - static void AllocateBuffers(unsigned int number); - - // Count how many buffers there are in a chain - static unsigned int Count(NetworkBuffer*& ptr); - - static const size_t bufferSize = -#ifdef USE_3K_BUFFERS - 3 * 1024; -#else - 2 * 1024; -#endif - -private: - NetworkBuffer(NetworkBuffer *n); - uint8_t *Data() { return reinterpret_cast<uint8_t*>(data32); } - const uint8_t *Data() const { return reinterpret_cast<const uint8_t*>(data32); } - - NetworkBuffer *next; - size_t dataLength; - size_t readPointer; -#ifdef DUET_WIFI - // When doing unaligned transfers on the WiFi interface, up to 3 extra bytes may be returned - uint32_t data32[bufferSize/sizeof(uint32_t) + 1]; // 32-bit aligned buffer so we can do direct DMA -#else - uint32_t data32[bufferSize/sizeof(uint32_t)]; // 32-bit aligned buffer so we can do direct DMA -#endif - static NetworkBuffer *freelist; -}; - -#endif /* SRC_DUETNG_DUETETHERNET_NETWORKBUFFER_H_ */ diff --git a/src/Network2/NetworkDefs.h b/src/Network2/NetworkDefs.h deleted file mode 100644 index e0182b5f..00000000 --- a/src/Network2/NetworkDefs.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * NetworkDefs.h - * - * Created on: 25 Dec 2016 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ -#define SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ - -#include <cstdint> -#include <cstddef> - -class Socket; -class NetworkBuffer; - -typedef uint8_t SocketNumber; - -typedef uint16_t Port; -typedef uint8_t Protocol; - -#ifndef DUET_WIFI -const uint8_t DefaultMacAddress[6] = { 0xBE, 0xEF, 0xDE, 0xAD, 0xFE, 0xED }; -#endif - -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 }; - -const size_t NumProtocols = 3; // number of network protocols we support, not counting FtpDataProtocol or AnyProtocol -const Protocol HttpProtocol = 0, FtpProtocol = 1, TelnetProtocol = 2, FtpDataProtocol = 3, AnyProtocol = 255; - -const Port DefaultHttpPort = 80; -const Port DefaultFtpPort = 21; -const Port DefaultTelnetPort = 23; - -const unsigned int TCP_MSS = 1460; - -const size_t NetworkBufferCount = 8; // number of 2K network buffers - -// Define the following to use 3K buffers on the W5500 for the HTTP sockets and smaller buffers for everything else -// It doesn't seem to work, the chip keeps telling us that 1 byte is available. -//#define USE_3K_BUFFERS 1 - -#endif /* SRC_DUETNG_DUETETHERNET_NETWORKDEFS_H_ */ diff --git a/src/Network2/NetworkResponder.cpp b/src/Network2/NetworkResponder.cpp deleted file mode 100644 index 6b84defb..00000000 --- a/src/Network2/NetworkResponder.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* - * NetworkResponder.cpp - * - * Created on: 14 Apr 2017 - * Author: David - */ - -#include "RepRapFirmware.h" -#include "NetworkResponder.h" -#include "Platform.h" -#include "OutputMemory.h" - -// NetworkResponderLock members - -// Acquire a lock -bool NetworkResponderLock::Acquire(const NetworkResponder *who) -{ - if (owner == nullptr) - { - owner = who; - return true; - } - if (owner == who) - { - return true; - } - return false; - -} - -// Release a lock -void NetworkResponderLock::Release(const NetworkResponder *who) -{ - if (owner == who) - { - owner = nullptr; - } -} - -// NetworkResponder members - -NetworkResponder::NetworkResponder(NetworkResponder *n) - : next(n), responderState(ResponderState::free), skt(nullptr), - outBuf(nullptr), outStack(new OutputStack), fileBeingSent(nullptr), fileBuffer(nullptr) -{ -} - -// Send the contents of the output buffers -void NetworkResponder::Commit(ResponderState nextState) -{ - stateAfterSending = nextState; - responderState = ResponderState::sending; - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Sending reply, file = %s\n", (fileBeingSent != nullptr) ? "yes" : "no"); - } -} - -// Send our data. -// We send outBuf first, then outStack, and finally fileBeingSent. -void NetworkResponder::SendData() -{ - // Send our output buffer and output stack - for(;;) - { - if (outBuf == nullptr) - { - outBuf = outStack->Pop(); - if (outBuf == nullptr) - { - break; - } - } - const size_t bytesLeft = outBuf->BytesLeft(); - if (bytesLeft == 0) - { - outBuf = OutputBuffer::Release(outBuf); - } - else - { - const size_t sent = skt->Send(reinterpret_cast<const uint8_t *>(outBuf->UnreadData()), bytesLeft); - if (sent == 0) - { - // Check whether the connection has been closed - if (!skt->CanSend()) - { - // The connection has been lost or the other end has closed it - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Can't send anymore\n"); - } - ConnectionLost(); - } - return; - } - - outBuf->Taken(sent); // tell the output buffer how much data we have taken - if (sent < bytesLeft) - { - return; - } - outBuf = OutputBuffer::Release(outBuf); - } - } - - // If we get here then there are no output buffers left to send - // If we have a file to send, send it - if (fileBeingSent != nullptr && fileBuffer == nullptr) - { - fileBuffer = NetworkBuffer::Allocate(); - if (fileBuffer == nullptr) - { - return; // no buffer available, try again later - } - } - - // If we have a file buffer here, we must be in the process of sending a file - while (fileBuffer != nullptr) - { - if (fileBuffer->IsEmpty() && fileBeingSent != nullptr) - { - const int bytesRead = fileBuffer->ReadFromFile(fileBeingSent); - if (bytesRead != (int)NetworkBuffer::bufferSize) - { - // We had a read error or we reached the end of the file - fileBeingSent->Close(); - fileBeingSent = nullptr; - } - } - - if (fileBuffer->IsEmpty()) - { - // Must have sent the whole file - fileBuffer->Release(); - fileBuffer = nullptr; - } - else - { - const size_t remaining = fileBuffer->Remaining(); - const size_t sent = skt->Send(fileBuffer->UnreadData(), remaining); - if (sent == 0) - { - // Check whether the connection has been closed - if (!skt->CanSend()) - { - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Can't send anymore\n"); - } - ConnectionLost(); - } - return; - } - - fileBuffer->Taken(sent); - if (sent < remaining) - { - return; - } - } - } - - // If we get here then there is nothing left to send - skt->Send(); // tell the socket there is no more data - - // If we are going to free up this responder after sending, then we must close the connection - if (stateAfterSending == ResponderState::free) - { - skt->Close(); - skt = nullptr; - } - responderState = stateAfterSending; -} - -// This is called when we lose a connection or when we are asked to terminate. Overridden in some derived classes. -void NetworkResponder::ConnectionLost() -{ - CancelUpload(); - OutputBuffer::ReleaseAll(outBuf); - outBuf = nullptr; - outStack->ReleaseAll(); - - if (fileBeingSent != nullptr) - { - fileBeingSent->Close(); - fileBeingSent = nullptr; - } - - if (fileBuffer != nullptr) - { - fileBuffer->Release(); - fileBuffer = nullptr; - } - - if (skt != nullptr) - { - skt->Terminate(); - skt = nullptr; - } - - responderState = ResponderState::free; -} - -// Start writing to a new file -void NetworkResponder::StartUpload(FileStore *file, const char *fileName) -{ - fileBeingUploaded.Set(file); - SafeStrncpy(filenameBeingUploaded, fileName, ARRAY_SIZE(filenameBeingUploaded)); - responderState = ResponderState::uploading; - uploadError = false; -} - -// If this responder has an upload in progress, cancel it -void NetworkResponder::CancelUpload() -{ - if (fileBeingUploaded.IsLive()) - { - fileBeingUploaded.Close(); - if (filenameBeingUploaded[0] != 0) - { - GetPlatform().GetMassStorage()->Delete(FS_PREFIX, filenameBeingUploaded); - } - } -} - -// Finish a file upload. Set variable uploadError if anything goes wrong. -void NetworkResponder::FinishUpload(uint32_t fileLength, time_t fileLastModified) -{ - // Flush remaining data for FSO - if (!fileBeingUploaded.Flush()) - { - uploadError = true; - GetPlatform().Message(ErrorMessage, "Could not flush remaining data while finishing upload!\n"); - } - - // Check the file length is as expected - if (fileLength != 0 && fileBeingUploaded.Length() != fileLength) - { - uploadError = true; - GetPlatform().MessageF(ErrorMessage, "Uploaded file size is different (%lu vs. expected %lu bytes)!\n", fileBeingUploaded.Length(), fileLength); - } - - // Close the file - if (fileBeingUploaded.IsLive()) - { - fileBeingUploaded.Close(); - } - - // Delete the file again if an error has occurred - if (filenameBeingUploaded[0] != 0) - { - if (uploadError) - { - GetPlatform().GetMassStorage()->Delete(FS_PREFIX, filenameBeingUploaded); - } - else if (fileLastModified != 0) - { - // Update the file timestamp if it was specified - (void)GetPlatform().GetMassStorage()->SetLastModifiedTime(nullptr, filenameBeingUploaded, fileLastModified); - } - } - - // Clean up again - filenameBeingUploaded[0] = 0; -} - -uint32_t NetworkResponder::GetRemoteIP() const -{ - return (skt == nullptr) ? 0 : skt->GetRemoteIP(); -} - -// End diff --git a/src/Network2/NetworkResponder.h b/src/Network2/NetworkResponder.h deleted file mode 100644 index ea492524..00000000 --- a/src/Network2/NetworkResponder.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * NetworkResponder.h - * - * Created on: 14 Apr 2017 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_NETWORKRESPONDER_H_ -#define SRC_DUETNG_DUETETHERNET_NETWORKRESPONDER_H_ - -#include "RepRapFirmware.h" -#include "RepRap.h" -#include "NetworkDefs.h" -#include "Socket.h" -#include "Storage/FileData.h" -#include "NetworkBuffer.h" - -// Forward declarations -class NetworkResponder; - -// Class to implement a simple lock -class NetworkResponderLock -{ -public: - NetworkResponderLock() : owner(nullptr) { } - - bool Acquire(const NetworkResponder *who); - void Release(const NetworkResponder *who); - bool IsOwnedBy(const NetworkResponder *who) const { return owner == who; } - -private: - const NetworkResponder *owner; -}; - -// Network responder base class -class NetworkResponder -{ -public: - NetworkResponder *GetNext() const { return next; } - virtual bool Spin() = 0; // do some work, returning true if we did anything significant - virtual bool Accept(Socket *s, Protocol protocol) = 0; // ask the responder to accept this connection, returns true if it did - virtual void Terminate(Protocol protocol) = 0; // terminate the responder if it is serving the specified protocol - virtual void Diagnostics(MessageType mtype) const = 0; - -protected: - // States machine control. Not all derived classes use all states. - enum class ResponderState - { - free = 0, // ready to be allocated - reading, // ready to receive data - sending, // sending data - uploading, // uploading a file to SD card - - // HTTP responder additional states - gettingFileInfoLock, // waiting to get the file info lock - gettingFileInfo, // getting file info - - // FTP responder additional states - waitingForPasvPort, - pasvPortOpened, - sendingPasvData, - pasvTransferComplete, - - // Telnet responder additional states - justConnected, - authenticating - }; - - NetworkResponder(NetworkResponder *n); - - void Commit(ResponderState nextState = ResponderState::free); - virtual void SendData(); - virtual void ConnectionLost(); - - void StartUpload(FileStore *file, const char *fileName); - void FinishUpload(uint32_t fileLength, time_t fileLastModified); - virtual void CancelUpload(); - - uint32_t GetRemoteIP() const; - - static Platform& GetPlatform() { return reprap.GetPlatform(); } - static Network& GetNetwork() { return reprap.GetNetwork(); } - - // General state - NetworkResponder *next; // next responder in the list - ResponderState responderState; // the current state - ResponderState stateAfterSending; // if we are sending, the state to enter when sending is complete - Socket *skt; - uint32_t timer; // a general purpose millisecond timer - - // Buffers for sending responses - OutputBuffer *outBuf; - OutputStack *outStack; - FileStore *fileBeingSent; - NetworkBuffer *fileBuffer; - - // File uploads - FileData fileBeingUploaded; - char filenameBeingUploaded[MaxFilenameLength]; - uint32_t postFileLength, uploadedBytes; // How many POST bytes do we expect and how many have already been written? - time_t fileLastModified; - bool uploadError; -}; - -#endif /* SRC_DUETNG_DUETETHERNET_NETWORKRESPONDER_H_ */ diff --git a/src/Network2/TelnetResponder.cpp b/src/Network2/TelnetResponder.cpp deleted file mode 100644 index 13f570c4..00000000 --- a/src/Network2/TelnetResponder.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - * TelnetResponder.cpp - * - * Created on: 15 Apr 2017 - * Author: David - */ - -#include "TelnetResponder.h" -#include "OutputMemory.h" -#include "GCodes/GCodes.h" -#include "Platform.h" - -TelnetResponder::TelnetResponder(NetworkResponder *n) : NetworkResponder(n) -{ -} - -// Ask the responder to accept this connection, returns true if it did -bool TelnetResponder::Accept(Socket *s, Protocol protocol) -{ - if (responderState == ResponderState::free && protocol == TelnetProtocol) - { - // Make sure we can get an output buffer before we accept the connection, or we won't be able to reply - if (outBuf != nullptr || OutputBuffer::Allocate(outBuf)) - { - skt = s; - clientPointer = 0; - responderState = ResponderState::justConnected; - connectTime = millis(); - haveCompleteLine = false; - if (reprap.Debug(moduleWebserver)) - { - debugPrintf("Telnet connection accepted\n"); - } - return true; - } - } - return false; -} - -// This is called to force termination if we implement the specified protocol -void TelnetResponder::Terminate(Protocol protocol) -{ - if (responderState != ResponderState::free && (protocol == TelnetProtocol || protocol == AnyProtocol)) - { - ConnectionLost(); - } -} - -// Do some work, returning true if we did anything significant -bool TelnetResponder::Spin() -{ - switch (responderState) - { - case ResponderState::free: - default: - return false; - - case ResponderState::justConnected: - if (millis() - connectTime < TelnetSetupDuration) - { - // Discard the setup message - char c; - while (skt->ReadChar(c)) { } - connectTime = 0; - return true; - } - - // Check whether we need a password to log in - if (reprap.NoPasswordSet()) - { - // Don't send a login prompt if no password is set, so we don't mess up Pronterface - responderState = ResponderState::reading; - } - else - { - outBuf->copy( "RepRapFirmware Telnet interface\r\n\r\n" - "Please enter your password:\r\n" - "> " - ); - Commit(ResponderState::authenticating); - } - return true; - - case ResponderState::authenticating: - { - bool readSomething = false; - char c; - while (!haveCompleteLine && skt->ReadChar(c)) - { - CharFromClient(c); - readSomething = true; - } - - if (!readSomething && !skt->CanRead()) - { - ConnectionLost(); - return true; - } - - if (haveCompleteLine && (outBuf != nullptr || OutputBuffer::Allocate(outBuf))) - { - haveCompleteLine = false; - clientPointer = 0; - if (reprap.CheckPassword(clientMessage)) - { - outBuf->copy("Log in successful!\r\n"); - Commit(ResponderState::reading); - } - else - { - outBuf->copy("Invalid password.\r\n> "); - Commit(ResponderState::authenticating); - } - return true; - } - return readSomething; - } - - case ResponderState::reading: - if (outBuf != nullptr && outBuf->BytesLeft() != 0) - { - // We have a gcode reply to send - Commit(ResponderState::reading); - return true; - } - { - bool readSomething = false; - char c; - while (!haveCompleteLine && skt->ReadChar(c)) - { - CharFromClient(c); - readSomething = true; - } - - if (!readSomething && !skt->CanRead()) - { - ConnectionLost(); - return true; - } - - if (haveCompleteLine) - { - ProcessLine(); - return true; - } - return readSomething; - } - - case ResponderState::sending: - SendData(); - return true; - } -} - -// Process a character from the client, returning true if we have a complete line -void TelnetResponder::CharFromClient(char c) -{ - switch (c) - { - case 0: - break; - - case '\b': - // Allow backspace for pure Telnet clients like PuTTY - if (clientPointer != 0) - { - clientPointer--; - } - break; - - case '\r': - case '\n': - if (clientPointer != 0) - { - // This line is complete - clientMessage[clientPointer] = 0; - haveCompleteLine = true; - } - break; - - default: - clientMessage[clientPointer++] = c; - - // Make sure we don't overflow the line buffer - if (clientPointer > ARRAY_UPB(clientMessage)) - { - clientPointer = 0; - GetPlatform().Message(UsbMessage, "Webserver: Buffer overflow in Telnet server!\n"); - } - break; - } -} - -// Usually we should not try to send any data here, because that would purge the packet's -// payload and mess with TCP streaming mode if Pronterface is used. However, under special -// circumstances this must happen. -void TelnetResponder::ProcessLine() -{ - // Special commands for Telnet - if (StringEquals(clientMessage, "exit") || StringEquals(clientMessage, "quit")) - { - if (outBuf != nullptr || OutputBuffer::Allocate(outBuf)) - { - haveCompleteLine = false; - clientPointer = 0; - - outBuf->copy("Goodbye.\r\n"); - Commit(); - } - } - else if (reprap.GetGCodes().GetTelnetInput()->BufferSpaceLeft() >= clientPointer + 1) - { - // All other codes are stored for the GCodes class - RegularGCodeInput * const telnetInput = reprap.GetGCodes().GetTelnetInput(); - telnetInput->Put(TelnetMessage, clientMessage); - haveCompleteLine = false; - clientPointer = 0; - } -} - -void TelnetResponder::HandleGCodeReply(const char *reply) -{ - if (reply != nullptr && (responderState == ResponderState::reading || responderState == ResponderState::sending)) - { - // We need a valid OutputBuffer to start the conversion from NL to CRNL - if (outBuf == nullptr) - { - if (!OutputBuffer::Allocate(outBuf)) - { - // No more space available to store this reply, stop here - return; - } - } - - // Write entire content to new output buffers, but this time with \r\n instead of \n - while (*reply != 0) - { - if (*reply == '\n' && outBuf->cat('\r') == 0) - { - // No more space available, stop here - return; - } - if (outBuf->cat(*reply) == 0) - { - // No more space available, stop here - return; - } - reply++; - } - } -} - -void TelnetResponder::HandleGCodeReply(OutputBuffer *reply) -{ - if (reply != nullptr && (responderState == ResponderState::reading || responderState == ResponderState::sending)) - { - // We need a valid OutputBuffer to start the conversion from NL to CRNL - if (outBuf == nullptr) - { - if (!OutputBuffer::Allocate(outBuf)) - { - OutputBuffer::Truncate(reply, OUTPUT_BUFFER_SIZE); - if (!OutputBuffer::Allocate(outBuf)) - { - // If we're really short on memory, release the G-Code reply instantly - OutputBuffer::ReleaseAll(reply); - return; - } - } - } - - // Write entire content to new output buffers, but this time with \r\n instead of \n - do { - const char *data = reply->Data(); - for(size_t i = 0; i < reply->DataLength(); i++) - { - if (*data == '\n') - { - outBuf->cat('\r'); - } - outBuf->cat(*data); - data++; - } - reply = OutputBuffer::Release(reply); - } while (reply != nullptr); - } - else - { - // Don't store buffers that may never get released... - OutputBuffer::ReleaseAll(reply); - } -} - -void TelnetResponder::Diagnostics(MessageType mt) const -{ - GetPlatform().MessageF(mt, " Telnet(%d)", (int)responderState); -} - -// End diff --git a/src/Network2/TelnetResponder.h b/src/Network2/TelnetResponder.h deleted file mode 100644 index c4f4d9ef..00000000 --- a/src/Network2/TelnetResponder.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * TelnetResponder.h - * - * Created on: 14 Apr 2017 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_TELNETRESPONDER_H_ -#define SRC_DUETNG_DUETETHERNET_TELNETRESPONDER_H_ - -#include "NetworkResponder.h" - -class TelnetResponder : public NetworkResponder -{ -public: - TelnetResponder(NetworkResponder *n); - bool Spin() override; // do some work, returning true if we did anything significant - bool Accept(Socket *s, Protocol protocol) override; // ask the responder to accept this connection, returns true if it did - void Terminate(Protocol protocol) override; // terminate the responder if it is serving the specified protocol - - void HandleGCodeReply(const char *reply); - void HandleGCodeReply(OutputBuffer *reply); - void Diagnostics(MessageType mtype) const override; - -private: - void CharFromClient(char c); - void ProcessLine(); - - bool haveCompleteLine; - char clientMessage[GCODE_LENGTH]; - size_t clientPointer; - uint32_t connectTime; - - static const uint32_t TelnetSetupDuration = 4000; // ignore the first Telnet request within this duration (in ms) -}; - -#endif /* SRC_DUETNG_DUETETHERNET_TELNETRESPONDER_H_ */ diff --git a/src/Network2/W5500/Network.cpp b/src/Network2/W5500/Network.cpp deleted file mode 100644 index 6cb6a0cc..00000000 --- a/src/Network2/W5500/Network.cpp +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Network.cpp - * - * Created on: 13 Dec 2016 - * Author: David - */ - -#include "Network.h" -#include "Wiznet/Ethernet/wizchip_conf.h" -#include "Wiznet/Internet/DHCP/dhcp.h" -#include "NetworkBuffer.h" -#include "Platform.h" -#include "RepRap.h" -#include "HttpResponder.h" -#include "FtpResponder.h" -#include "TelnetResponder.h" -#include "Libraries/General/IP4String.h" - -const Port DefaultPortNumbers[NumProtocols] = { DefaultHttpPort, DefaultFtpPort, DefaultTelnetPort }; -const char * const ProtocolNames[NumProtocols] = { "HTTP", "FTP", "TELNET" }; - -Network::Network(Platform& p) - : platform(p), nextResponderToPoll(nullptr), lastTickMillis(0), - state(NetworkState::disabled), activated(false) -{ - for (size_t i = 0; i < NumProtocols; ++i) - { - portNumbers[i] = DefaultPortNumbers[i]; - protocolEnabled[i] = (i == HttpProtocol); - } - - // Create the responders - responders = telnetResponder = new TelnetResponder(nullptr); - responders = ftpResponder = new FtpResponder(responders); - for (unsigned int i = 0; i < NumHttpResponders; ++i) - { - responders = new HttpResponder(responders); - } -} - -void Network::Init() -{ - // Ensure that the W5500 chip is in the reset state - pinMode(W5500ResetPin, OUTPUT_LOW); - longWait = millis(); - lastTickMillis = millis(); - - NetworkBuffer::AllocateBuffers(NetworkBufferCount); - - SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway); - strcpy(hostname, HOSTNAME); -} - -void Network::EnableProtocol(int protocol, int port, int secure, const StringRef& reply) -{ - if (secure != 0 && secure != -1) - { - reply.copy("Error: this firmware does not support TLS"); - } - else if (protocol >= 0 && protocol < (int)NumProtocols) - { - const Port portToUse = (port < 0) ? DefaultPortNumbers[protocol] : port; - if (portToUse != portNumbers[protocol] && state == NetworkState::active) - { - // We need to shut down and restart the protocol if it is active because the port number has changed - ShutdownProtocol(protocol); - protocolEnabled[protocol] = false; - } - portNumbers[protocol] = portToUse; - if (!protocolEnabled[protocol]) - { - protocolEnabled[protocol] = true; - if (state == NetworkState::active) - { - StartProtocol(protocol); -#if 0 // mdns not implemented yet - if (state == NetworkState::active) - { - DoMdnsAnnounce(); - } -#endif - } - } - ReportOneProtocol(protocol, reply); - } - else - { - reply.copy("Invalid protocol parameter"); - } -} - -void Network::DisableProtocol(int protocol, const StringRef& reply) -{ - if (protocol >= 0 && protocol < (int)NumProtocols) - { - if (state == NetworkState::active) - { - ShutdownProtocol(protocol); - } - protocolEnabled[protocol] = false; - ReportOneProtocol(protocol, reply); - } - else - { - reply.copy("Invalid protocol parameter"); - } -} - -void Network::StartProtocol(Protocol protocol) -{ - switch(protocol) - { - case HttpProtocol: - for (SocketNumber skt = 0; skt < NumHttpSockets; ++skt) - { - sockets[skt].Init(skt, portNumbers[protocol], protocol); - } - break; - - case FtpProtocol: - sockets[FtpSocketNumber].Init(FtpSocketNumber, portNumbers[protocol], protocol); - break; - - case TelnetProtocol: - sockets[TelnetSocketNumber].Init(TelnetSocketNumber, portNumbers[protocol], protocol); - break; - - default: - break; - } -} - -void Network::ShutdownProtocol(Protocol protocol) -{ - for (NetworkResponder* r = responders; r != nullptr; r = r->GetNext()) - { - r->Terminate(protocol); - } - - switch(protocol) - { - case HttpProtocol: - for (SocketNumber skt = 0; skt < NumHttpSockets; ++skt) - { - sockets[skt].TerminateAndDisable(); - } - break; - - case FtpProtocol: - sockets[FtpSocketNumber].TerminateAndDisable(); - sockets[FtpDataSocketNumber].TerminateAndDisable(); - break; - - case TelnetProtocol: - sockets[TelnetSocketNumber].TerminateAndDisable(); - break; - - default: - break; - } -} - -// Report the protocols and ports in use -void Network::ReportProtocols(const StringRef& reply) const -{ - reply.Clear(); - for (size_t i = 0; i < NumProtocols; ++i) - { - if (i != 0) - { - reply.cat('\n'); - } - ReportOneProtocol(i, reply); - } -} - -void Network::ReportOneProtocol(Protocol protocol, const StringRef& reply) const -{ - if (protocolEnabled[protocol]) - { - reply.catf("%s is enabled on port %u", ProtocolNames[protocol], portNumbers[protocol]); - } - else - { - reply.catf("%s is disabled", ProtocolNames[protocol]); - } -} - -// This is called at the end of config.g processing. -// Start the network if it was enabled -void Network::Activate() -{ - if (!activated) - { - activated = true; - if (state == NetworkState::enabled) - { - Start(); - } - else - { - platform.Message(NetworkInfoMessage, "Network disabled.\n"); - } - } -} - -void Network::Exit() -{ - Stop(); -} - -// Get the network state into the reply buffer, returning true if there is some sort of error -bool Network::GetNetworkState(const StringRef& reply) -{ - const uint8_t * const config_ip = platform.GetIPAddress(); - const int enableState = EnableState(); - reply.printf("Network is %s, configured IP address: %s, actual IP address: %s", - (enableState == 0) ? "disabled" : "enabled", - IP4String(config_ip).c_str(), IP4String(ipAddress).c_str()); - return false; -} - -// Start up the network -void Network::Start() -{ - SetIPAddress(platform.GetIPAddress(), platform.NetMask(), platform.GateWay()); - pinMode(W5500ResetPin, OUTPUT_LOW); - delayMicroseconds(550); // W550 reset pulse must be at least 500us long - IoPort::WriteDigital(W5500ResetPin, HIGH); // raise /Reset pin - delay(55); // W5500 needs 50ms to start up - -#ifdef USE_3K_BUFFERS - static const uint8_t bufSizes[8] = { 3, 3, 3, 3, 1, 1, 1, 1 }; // 3K buffers for http, 1K for everything else (FTP will be slow) -#else - static const uint8_t bufSizes[8] = { 2, 2, 2, 2, 2, 2, 2, 2 }; // 2K buffers for everything -#endif - - wizchip_init(bufSizes, bufSizes); - - setSHAR(platform.MACAddress()); - setSIPR(ipAddress); - setGAR(gateway); - setSUBR(netmask); - - state = NetworkState::establishingLink; -} - -// Stop the network -void Network::Stop() -{ - if (state != NetworkState::disabled) - { - for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) - { - r->Terminate(AnyProtocol); - } - if (usingDhcp) - { - DHCP_stop(); - } - digitalWrite(W5500ResetPin, LOW); // put the W5500 back into reset - state = NetworkState::disabled; - } -} - -// 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) - { - case NetworkState::enabled: - case NetworkState::disabled: - default: - // Nothing to do - break; - - case NetworkState::establishingLink: - if (full && wizphy_getphylink() == PHY_LINK_ON) - { - usingDhcp = (ipAddress[0] == 0 && ipAddress[1] == 0 && ipAddress[2] == 0 && ipAddress[3] == 0); - if (usingDhcp) - { - // IP address is all zeros, so use DHCP -// debugPrintf("Link established, getting IP address\n"); - DHCP_init(DhcpSocketNumber, hostname); - lastTickMillis = millis(); - state = NetworkState::obtainingIP; - } - else - { -// debugPrintf("Link established, network running\n"); - state = NetworkState::connected; - } - } - break; - - case NetworkState::obtainingIP: - if (full) - { - if (wizphy_getphylink() == PHY_LINK_ON) - { - 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(); - state = NetworkState::connected; - } - } - else - { -// debugPrintf("Lost phy link\n"); - DHCP_stop(); - TerminateSockets(); - state = NetworkState::establishingLink; - } - } - break; - - case NetworkState::connected: - if (full) - { - InitSockets(); - platform.MessageF(NetworkInfoMessage, "Network running, IP address = %s\n", IP4String(ipAddress).c_str()); - state = NetworkState::active; - } - break; - - case NetworkState::active: - // Check that the link is still up - if (wizphy_getphylink() == PHY_LINK_ON) - { - // Maintain DHCP - if (full && usingDhcp) - { - const uint32_t now = millis(); - if (now - lastTickMillis >= 1000) - { - lastTickMillis += 1000; - DHCP_time_handler(); - } - const DhcpRunResult ret = DHCP_run(); - if (ret == DhcpRunResult::DHCP_IP_CHANGED) - { -// debugPrintf("IP address changed\n"); - getSIPR(ipAddress); - } - } - - // 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; - } - - // Poll the responders - if (full) - { - NetworkResponder *nr = nextResponderToPoll; - bool doneSomething = false; - do - { - if (nr == nullptr) - { - nr = responders; // 'responders' can't be null at this point - } - doneSomething = nr->Spin(); - nr = nr->GetNext(); - } while (!doneSomething && nr != nextResponderToPoll); - nextResponderToPoll = nr; - } - } - else if (full) - { -// debugPrintf("Lost phy link\n"); - if (usingDhcp) - { - DHCP_stop(); - } - TerminateSockets(); - state = NetworkState::establishingLink; - } - break; - } - - if (full) - { - platform.ClassReport(longWait); - } -} - -void Network::Diagnostics(MessageType mtype) -{ - platform.MessageF(mtype, "=== Network ===\nState: %d\n", (int)state); - HttpResponder::CommonDiagnostics(mtype); - platform.Message(mtype, "Responder states:"); - for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) - { - r->Diagnostics(mtype); - } - platform.Message(mtype, "\n"); -} - -// Enable or disable the network -void Network::Enable(int mode, const StringRef& reply) -{ - if (!activated) - { - state = (mode == 0) ? NetworkState::disabled : NetworkState::enabled; - } - else if (mode == 0) - { - if (state != NetworkState::disabled) - { - Stop(); - platform.Message(NetworkInfoMessage, "Network stopped\n"); - } - - } - else if (state == NetworkState::disabled) - { - state = NetworkState::enabled; - Start(); - } -} - -int Network::EnableState() const -{ - return (state == NetworkState::disabled) ? 0 : 1; -} - -void Network::SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]) -{ - memcpy(ipAddress, p_ipAddress, sizeof(ipAddress)); - memcpy(netmask, p_netmask, sizeof(netmask)); - memcpy(gateway, p_gateway, sizeof(gateway)); -} - -void Network::SetHostname(const char *name) -{ - size_t i = 0; - while (*name && i < ARRAY_UPB(hostname)) - { - char c = *name++; - if (c >= 'A' && c <= 'Z') - { - c += 'a' - 'A'; - } - - if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '-') || (c == '_')) - { - hostname[i++] = c; - } - } - - if (i != 0) - { - hostname[i] = 0; - } - else - { - strcpy(hostname, HOSTNAME); - } -} - -void Network::OpenDataPort(Port port) -{ - sockets[FtpDataSocketNumber].Init(FtpDataSocketNumber, port, FtpDataProtocol); -} - -// Close FTP data port and purge associated resources -void Network::TerminateDataPort() -{ - sockets[FtpDataSocketNumber].Terminate(); -} - -void Network::InitSockets() -{ - for (size_t i = 0; i < NumProtocols; ++i) - { - if (protocolEnabled[i]) - { - StartProtocol(i); - } - } - nextSocketToPoll = 0; -} - -// The following is called by the FTP responder to stop listening on the FTP data port -// For the W5500 listening stop automatically when the port is terminated, so we don't need anything here -void Network::DataPortClosing() -{ - // nothing needed here -} - -void Network::TerminateSockets() -{ - for (SocketNumber skt = 0; skt < NumTcpSockets; ++skt) - { - sockets[skt].Terminate(); - } -} - -// Find a responder to process a new connection -bool Network::FindResponder(Socket *skt, Protocol protocol) -{ - for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) - { - if (r->Accept(skt, protocol)) - { - return true; - } - } - return false; -} - -void Network::HandleHttpGCodeReply(const char *msg) -{ - HttpResponder::HandleGCodeReply(msg); -} - -void Network::HandleTelnetGCodeReply(const char *msg) -{ - telnetResponder->HandleGCodeReply(msg); -} - -void Network::HandleHttpGCodeReply(OutputBuffer *buf) -{ - HttpResponder::HandleGCodeReply(buf); -} - -void Network::HandleTelnetGCodeReply(OutputBuffer *buf) -{ - telnetResponder->HandleGCodeReply(buf); -} - -uint32_t Network::GetHttpReplySeq() -{ - return HttpResponder::GetReplySeq(); -} - -// End diff --git a/src/Network2/W5500/Network.h b/src/Network2/W5500/Network.h deleted file mode 100644 index cdf609c0..00000000 --- a/src/Network2/W5500/Network.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************************************** - -RepRapFirmware - Network: RepRapPro Ormerod with Duet controller - -Separated out from Platform.h by dc42 and extended by chrishamm - -****************************************************************************************************/ - -#ifndef NETWORK_H -#define NETWORK_H - -#include "Socket.h" -#include "NetworkDefs.h" -#include "MessageType.h" - -class NetworkResponder; -class HttpResponder; -class FtpResponder; -class TelnetResponder; - -// We have 8 sockets available on the W5500. -const size_t NumHttpSockets = 4; // sockets 0-3 are for HTTP -const SocketNumber FtpSocketNumber = 4; -const SocketNumber FtpDataSocketNumber = 5; // TODO can we allocate this dynamically when required, to allow more http sockets most of the time? -const SocketNumber TelnetSocketNumber = 6; -const size_t NumTcpSockets = 7; -const SocketNumber DhcpSocketNumber = 7; // TODO can we allocate this dynamically when required, to allow more http sockets most of the time? - -const unsigned int NumHttpResponders = 4; // the number of concurrent HTTP requests we can process - -class Platform; - -// The main network class that drives the network. -class Network -{ -public: - Network(Platform& p); - - void Init(); - void Activate(); - void Exit(); - void Spin(bool full); - void Diagnostics(MessageType mtype); - void Start(); - void Stop(); - - void EnableProtocol(int protocol, int port, int secure, const StringRef& reply); - void DisableProtocol(int protocol, const StringRef& reply); - void ReportProtocols(const StringRef& reply) const; - - void Enable(int mode, const StringRef& reply); // enable or disable the network - bool GetNetworkState(const StringRef& reply); - int EnableState() const; - - void SetHostname(const char *name); - - bool FindResponder(Socket *skt, Protocol protocol); - - const uint8_t *GetIPAddress() const { return ipAddress; } - void OpenDataPort(Port port); - void TerminateDataPort(); - void DataPortClosing(); - - void HandleHttpGCodeReply(const char *msg); - void HandleTelnetGCodeReply(const char *msg); - void HandleHttpGCodeReply(OutputBuffer *buf); - void HandleTelnetGCodeReply(OutputBuffer *buf); - uint32_t GetHttpReplySeq(); - -private: - enum class NetworkState - { - disabled, // Network disabled - enabled, // Network enabled but not started yet - establishingLink, // starting up, waiting for link - obtainingIP, // link established, waiting for DHCP - connected, // just established a connection - active // network running - }; - - void InitSockets(); - void TerminateSockets(); - - void StartProtocol(Protocol protocol) - pre(protocol < NumProtocols); - - void ShutdownProtocol(Protocol protocol) - pre(protocol < NumProtocols); - - void ReportOneProtocol(Protocol protocol, const StringRef& reply) const - pre(protocol < NumProtocols); - - void SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]); - - Platform& platform; - NetworkResponder *responders; - NetworkResponder *nextResponderToPoll; - FtpResponder *ftpResponder; - TelnetResponder *telnetResponder; - uint32_t longWait; - uint32_t lastTickMillis; - - Socket sockets[NumTcpSockets]; - size_t nextSocketToPoll; // next TCP socket number to poll for read/write operations - - Port portNumbers[NumProtocols]; // port number used for each protocol - bool protocolEnabled[NumProtocols]; // whether each protocol is enabled - - NetworkState state; - bool activated; - bool usingDhcp; - - uint8_t ipAddress[4]; - uint8_t netmask[4]; - uint8_t gateway[4]; - char hostname[16]; // Limit DHCP hostname to 15 characters + terminating 0 -}; - -#endif diff --git a/src/Network2/W5500/Socket.cpp b/src/Network2/W5500/Socket.cpp deleted file mode 100644 index 8ff7bab8..00000000 --- a/src/Network2/W5500/Socket.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Socket.cpp - * - * Created on: 25 Dec 2016 - * Author: David - */ - -#include <Network2/W5500/Network.h> -#include <Network2/W5500/Socket.h> -#include <Network2/W5500/Wiznet/Ethernet/socketlib.h> -#include "NetworkBuffer.h" -#include "RepRap.h" - -//*************************************************************************************************** -// Socket class - -const uint32_t FindResponderTimeout = 2000; // how long we wait for a responder to become available -const unsigned int MaxBuffersPerSocket = 4; - -Socket::Socket() : receivedData(nullptr), state(SocketState::disabled) -{ -} - -// Initialise a TCP socket -void Socket::Init(SocketNumber skt, Port serverPort, Protocol p) -{ - socketNum = skt; - localPort = serverPort; - protocol = p; - ReInit(); -} - -void Socket::TerminateAndDisable() -{ - Terminate(); - state = SocketState::disabled; -} - -void Socket::ReInit() -{ - // Discard any received data - while (receivedData != nullptr) - { - receivedData = receivedData->Release(); - } - - persistConnection = true; - isTerminated = false; - isSending = false; - state = SocketState::inactive; - - // Re-initialise the socket on the W5500 - socket(socketNum, Sn_MR_TCP, localPort, 0x00); -} - -// Close a connection when the last packet has been sent -void Socket::Close() -{ - if (state != SocketState::disabled && state != SocketState::inactive) - { - ExecCommand(socketNum, Sn_CR_DISCON); - state = SocketState::closing; - DiscardReceivedData(); - if (protocol == FtpDataProtocol) - { - localPort = 0; // don't re-listen automatically - } - } -} - -// Terminate a connection immediately -void Socket::Terminate() -{ - if (state != SocketState::disabled) - { - disconnectNoWait(socketNum); - isTerminated = true; - state = SocketState::inactive; - DiscardReceivedData(); - } -} - -// Return true if there is or may soon be more data to read -bool Socket::CanRead() const -{ - return (state == SocketState::connected) - || (state == SocketState::clientDisconnecting && receivedData != nullptr && receivedData->TotalRemaining() != 0); -} - -bool Socket::CanSend() const -{ - return state == SocketState::connected; -} - -// Read 1 character from the receive buffers, returning true if successful -bool Socket::ReadChar(char& c) -{ - if (receivedData != nullptr) - { - const bool ret = receivedData->ReadChar(c); - if (receivedData->IsEmpty()) - { - receivedData = receivedData->Release(); - } - return ret; - } - - c = 0; - return false; -} - -// Return a pointer to data in a buffer and a length available -bool Socket::ReadBuffer(const uint8_t *&buffer, size_t &len) -{ - if (receivedData != nullptr) - { - len = receivedData->Remaining(); - buffer = receivedData->UnreadData(); - return true; - } - - return false; -} - -// Flag some data as taken from the receive buffers. We never take data from more than one buffer at a time. -void Socket::Taken(size_t len) -{ - if (receivedData != nullptr) - { - receivedData->Taken(len); - if (receivedData->IsEmpty()) - { - receivedData = receivedData->Release(); // discard empty buffer at head of chain - } - } -} - -// Poll a socket to see if it needs to be serviced -void Socket::Poll(bool full) -{ - if (state != SocketState::disabled) - { - switch(getSn_SR(socketNum)) - { - case SOCK_INIT: - // 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 - { - ExecCommand(socketNum, Sn_CR_LISTEN); - state = SocketState::listening; - } - break; - - case SOCK_LISTEN: // Socket is listening but no client has connected to it yet - break; - - case SOCK_ESTABLISHED: // A client is connected to this socket - if (getSn_IR(socketNum) & Sn_IR_CON) - { - // New connection, so retrieve the sending IP address and port, and clear the interrupt - getSn_DIPR(socketNum, reinterpret_cast<uint8_t*>(&remoteIPAddress)); - remotePort = getSn_DPORT(socketNum); - setSn_IR(socketNum, Sn_IR_CON); - whenConnected = millis(); - } - - if (full && state == SocketState::listening) // if it is a new connection - { - if (reprap.GetNetwork().FindResponder(this, protocol)) - { - state = SocketState::connected; - sendOutstanding = false; - } - else - { - if (millis() - whenConnected >= FindResponderTimeout) - { - Terminate(); - } - } - } - - if (state == SocketState::connected) - { - // See if the socket has received any data - ReceiveData(); - } - break; - - case SOCK_CLOSE_WAIT: // A client has asked to disconnect - // Check for further incoming packets before this socket is finally closed. - // This must be done to ensure that FTP uploads are not cut off. - ReceiveData(); - - state = SocketState::clientDisconnecting; - break; - - case SOCK_CLOSED: - ReInit(); - break; - - default: - break; - } - } -} - -// Try to receive more incoming data from the socket -void Socket::ReceiveData() -{ - const uint16_t len = getSn_RX_RSR(socketNum); - if (len != 0) - { -// debugPrintf("%u available\n", len); - NetworkBuffer * const lastBuffer = NetworkBuffer::FindLast(receivedData); - if (lastBuffer != nullptr && (lastBuffer->SpaceLeft() >= len || (lastBuffer->SpaceLeft() != 0 && NetworkBuffer::Count(receivedData) >= MaxBuffersPerSocket))) - { - const size_t lengthToRead = min<size_t>((size_t)len, lastBuffer->SpaceLeft()); - wiz_recv_data(socketNum, lastBuffer->UnwrittenData(), (uint16_t)lengthToRead); - lastBuffer->dataLength += lengthToRead; - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Received %u bytes\n", (unsigned int)lengthToRead); - } - } - else if (NetworkBuffer::Count(receivedData) < MaxBuffersPerSocket) - { - NetworkBuffer * const buf = NetworkBuffer::Allocate(); - if (buf != nullptr) - { - wiz_recv_data(socketNum, buf->Data(), len); - ExecCommand(socketNum, Sn_CR_RECV); - buf->dataLength = (size_t)len; - NetworkBuffer::AppendToList(&receivedData, buf); - if (reprap.Debug(moduleNetwork)) - { - debugPrintf("Received %u bytes\n", (unsigned int)len); - } - } - } -// else debugPrintf("no buffer\n"); - } -} - -// Discard any received data for this transaction -void Socket::DiscardReceivedData() -{ - while (receivedData != nullptr) - { - receivedData = receivedData->Release(); - } -} - -// Send the data, returning the length buffered -size_t Socket::Send(const uint8_t *data, size_t length) -{ - if (CanSend() && length != 0 && getSn_SR(socketNum) == SOCK_ESTABLISHED) - { - // Check for previous send complete - 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 - state = SocketState::aborted; - return 0; // and release buffers etc. - } - else - { - return 0; // last send is still in progress - } - } - - if (!sendOutstanding) - { - wizTxBufferLeft = getSn_TX_FSR(socketNum); // get free buffer space - if (wizTxBufferLeft == 0) - { - return 0; - } - wizTxBufferPtr = getSn_TX_WR(socketNum); - } - - if (length > wizTxBufferLeft) - { - length = wizTxBufferLeft; - } - wiz_send_data_at(socketNum, data, length, wizTxBufferPtr); - wizTxBufferLeft -= length; - wizTxBufferPtr += length; - sendOutstanding = true; - if (wizTxBufferLeft == 0) - { - Send(); - } - return length; - } - return 0; -} - -// Tell the interface to send the outstanding data -void Socket::Send() -{ - if (CanSend() && sendOutstanding) - { - setSn_TX_WR(socketNum, wizTxBufferPtr); - ExecCommand(socketNum, Sn_CR_SEND); - isSending = true; - sendOutstanding = false; - } -} - -// End diff --git a/src/Network2/W5500/Socket.h b/src/Network2/W5500/Socket.h deleted file mode 100644 index 6d211e5e..00000000 --- a/src/Network2/W5500/Socket.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Socket.h - * - * Created on: 25 Dec 2016 - * Author: David - */ - -#ifndef SRC_DUETNG_DUETETHERNET_SOCKET_H_ -#define SRC_DUETNG_DUETETHERNET_SOCKET_H_ - -#include "RepRapFirmware.h" -#include "NetworkDefs.h" - -// Socket structure that we use to track TCP connections -class Socket -{ -public: - Socket(); - void Init(SocketNumber s, Port serverPort, Protocol p); - void TerminateAndDisable(); - void Poll(bool full); - Port GetLocalPort() const { return localPort; } - uint32_t GetRemoteIP() const { return remoteIPAddress; } - Port GetRemotePort() const { return remotePort; } - void Close(); - void Terminate(); - bool ReadChar(char& c); - bool ReadBuffer(const uint8_t *&buffer, size_t &len); - void Taken(size_t len); - bool CanRead() const; - bool CanSend() const; - size_t Send(const uint8_t *data, size_t length); - void Send(); - -private: - enum class SocketState : uint8_t - { - disabled, - inactive, - listening, - connected, - clientDisconnecting, - closing, - aborted - }; - - void ReInit(); - void ReceiveData(); - void DiscardReceivedData(); - - Port localPort, remotePort; // The local and remote ports - Protocol protocol; // What protocol this socket is for - uint32_t remoteIPAddress; // The remote IP address - NetworkBuffer *receivedData; // List of buffers holding received data - //invariant(!receivedData->IsEmpty()) - uint32_t whenConnected; - 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 sendOutstanding; // True if we have written data to the socket but not flushed it - bool isSending; // True if we have written data to the W5500 to send and have not yet seen success or timeout - uint16_t wizTxBufferPtr; // Current offset into the Wizchip send buffer, if sendOutstanding is true - uint16_t wizTxBufferLeft; // Transmit buffer space left, if sendOutstanding is true -}; - -#endif /* SRC_DUETNG_DUETETHERNET_SOCKET_H_ */ diff --git a/src/Network2/W5500/Wiznet/.gitattributes b/src/Network2/W5500/Wiznet/.gitattributes deleted file mode 100644 index 412eeda7..00000000 --- a/src/Network2/W5500/Wiznet/.gitattributes +++ /dev/null @@ -1,22 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/src/Network2/W5500/Wiznet/.gitignore b/src/Network2/W5500/Wiznet/.gitignore deleted file mode 100644 index 58bcbf82..00000000 --- a/src/Network2/W5500/Wiznet/.gitignore +++ /dev/null @@ -1,43 +0,0 @@ -# Windows image file caches
-Thumbs.db
-ehthumbs.db
-
-# Folder config file
-Desktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msm
-*.msp
-
-# =========================
-# Operating System Files
-# =========================
-
-# OSX
-# =========================
-
-.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon
- -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk diff --git a/src/Network2/W5500/Wiznet/Ethernet/Socket_APIs_V3.0.3.chm b/src/Network2/W5500/Wiznet/Ethernet/Socket_APIs_V3.0.3.chm Binary files differdeleted file mode 100644 index 35ed5128..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/Socket_APIs_V3.0.3.chm +++ /dev/null diff --git a/src/Network2/W5500/Wiznet/Ethernet/W5500/w5500.cpp b/src/Network2/W5500/Wiznet/Ethernet/W5500/w5500.cpp deleted file mode 100644 index 4467605c..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/W5500/w5500.cpp +++ /dev/null @@ -1,177 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.cpp -//! \brief W5500 HAL Interface. -//! \version 1.0.2 -//! \date 2013/10/21 -//! \par Revision history -//! <2015/02/05> Notice -//! The version history is not updated after this point. -//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. -//! >> https://github.com/Wiznet/ioLibrary_Driver -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include <Network2/W5500/Wiznet/Ethernet/W5500/w5500.h> -#include <Network2/W5500/Wiznet/Ethernet/WizSpi.h> - -#define _W5500_SPI_VDM_OP_ 0x00 -#define _W5500_SPI_FDM_OP_LEN1_ 0x01 -#define _W5500_SPI_FDM_OP_LEN2_ 0x02 -#define _W5500_SPI_FDM_OP_LEN4_ 0x03 - -//////////////////////////////////////////////////// - -uint8_t WIZCHIP_READ(uint32_t AddrSel) -{ - WizSpi::AssertSS(); - WizSpi::SendAddress(AddrSel | (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_)); - const uint8_t ret = WizSpi::ReadByte(); - WizSpi::ReleaseSS(); - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) -{ - WizSpi::AssertSS(); - WizSpi::SendAddress(AddrSel | (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_)); - WizSpi::WriteByte(wb); - WizSpi::ReleaseSS(); -} - -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - WizSpi::AssertSS(); - WizSpi::SendAddress(AddrSel | (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_)); - WizSpi::ReadBurst(pBuf, len); - WizSpi::ReleaseSS(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, const uint8_t* pBuf, uint16_t len) -{ - WizSpi::AssertSS(); - WizSpi::SendAddress(AddrSel | (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_)); - WizSpi::SendBurst(pBuf, len); - WizSpi::ReleaseSS(); -} - - -uint16_t getSn_TX_FSR(uint8_t sn) -{ - uint16_t val = 0, val1 = 0; - do - { - val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_TX_FSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - } - } while (val != val1); - return val; -} - -uint16_t getSn_RX_RSR(uint8_t sn) -{ - uint16_t val = 0, val1 = 0; - do - { - val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_RX_RSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - } - } while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, const uint8_t *wizdata, uint16_t len) -{ - if (len != 0) - { - uint16_t ptr = getSn_TX_WR(sn); - 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); - } -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - if (len != 0) - { - uint16_t ptr = getSn_RX_RD(sn); - const uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - WIZCHIP_READ_BUF(addrsel, wizdata, len); - ptr += len; - - setSn_RX_RD(sn,ptr); - } -} - - -void wiz_recv_ignore(uint8_t sn, uint16_t len) -{ - uint16_t ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn,ptr); -} - -// End diff --git a/src/Network2/W5500/Wiznet/Ethernet/W5500/w5500.h b/src/Network2/W5500/Wiznet/Ethernet/W5500/w5500.h deleted file mode 100644 index 723bd7bf..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/W5500/w5500.h +++ /dev/null @@ -1,2299 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2015/02/05> Notice -//! The version history is not updated after this point. -//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. -//! >> https://github.com/Wiznet/ioLibrary_Driver -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -// - -#ifndef _W5500_H_ -#define _W5500_H_ - -#include <Network2/W5500/Wiznet/Ethernet/wizchip_conf.h> -#include <cstdint> -#include <cstddef> -#include "spi/spi.h" - -// The following functions are defined in Network.cpp and used by this module -extern void SpiAssertSS(); -extern void SpiReleaseSS(); -extern void SpiSendAddress(uint32_t); -extern uint8_t SpiReadByte(); -extern void SpiSendByte(uint8_t b); -extern spi_status_t SpiReadBurst(uint8_t* pBuf, size_t len); -extern spi_status_t SpiSendBurst(const uint8_t* pBuf, size_t len); - - -#define _W5500_IO_BASE_ 0x00000000 - -#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase -#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase - -#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block -#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block -#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block -#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block - -#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address - - -/////////////////////////////////////// -// Definition For Legacy Chip Driver // -/////////////////////////////////////// -#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver -#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver -#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver -#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - <b> Basic I/O function </b> \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group <b>access functions</b> \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# <b> Network Information </b> \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# <b> ICMP packet </b>\n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group <b>access functions</b> \n - * -# <b> SOCKET control</b> \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# <b> SOCKET information</b> \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# <b> SOCKET communication </b> \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# <b> IP header field </b> \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa _RTR_, _RCR_ : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access <b>common registers</b>. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access <b>socket registers</b>. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * <table> - * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> - * <tr> <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>FARP</td> <td>Reserved</td> </tr> - * </table> - * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -const uint32_t MR = _W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ - const uint32_t GAR = _W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ - const uint32_t SUBR = _W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ - const uint32_t SHAR = _W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ - const uint32_t SIPR = _W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ - const uint32_t INTLEVEL = _W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * <table> - * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> - * <tr> <td>CONFLICT</td> <td>UNREACH</td> <td>PPPoE</td> <td>MP</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr> - * </table> - * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ - const uint32_t IR = _W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref _IMR_ is used to mask interrupts. Each bit of @ref _IMR_ corresponds to each bit of @ref IR. - * When a bit of @ref _IMR_ is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref _IMR_ is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref _IMR_ defined as the following. - * <table> - * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> - * <tr> <td>IM_IR7</td> <td>IM_IR6</td> <td>IM_IR5</td> <td>IM_IR4</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr> - * </table> - * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ - const uint32_t _IMR_ = _W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ - const uint32_t SIR = _W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ - const uint32_t SIMR = _W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref _RTR_ is x07D0. - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref _RTR_, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref _RTR_ time, W5500 retransmits the packet or issues timeout. - */ - const uint32_t _RTR_ = _W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref _RCR_ configures the number of time of retransmission. - * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (@ref Sn_IR_TIMEOUT = '1'). - */ - const uint32_t _RCR_ = _W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ - const uint32_t PTIMER = _W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ - const uint32_t PMAGIC = _W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ - const uint32_t PHAR = _W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ - const uint32_t PSID = _W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ - const uint32_t PMRU = _W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref IR_UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ - const uint32_t UIPR = _W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref IR_UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ - const uint32_t UPORTR = _W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3); - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ - const uint32_t PHYCFGR = _W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3); - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ - const uint32_t VERSIONR = _W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3); - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * <table> - * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> - * <tr> <td>MULTI/MFEN</td> <td>BCASTB</td> <td>ND/MC/MMB</td> <td>UCASTB/MIP6B</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr> - * </table> - * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block <b>in UDP Multicasting</b> - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used <b>in UDP mulitcasting</b> - * - @ref Sn_MR_MMB : Multicast Blocking <b>in @ref Sn_MR_MACRAW mode</b> - * - @ref Sn_MR_UCASTB : Unicast Block <b>in UDP Multicating</b> - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking <b>in @ref Sn_MR_MACRAW mode</b> - * - <b>Protocol</b> - * <table> - * <tr> <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td> </tr> - * <tr> <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td> </tr> - * <tr> <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td> </tr> - * <tr> <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td> </tr> - * <tr> <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td> </tr> - * </table> - * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ - static inline uint32_t Sn_MR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(<b>Server mode</b>) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(<b>Client mode</b>) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ - static inline uint32_t Sn_CR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * <table> - * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> - * <tr> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr> - * </table> - * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b> - * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b> - * - \ref Sn_IR_RECV : <b>RECV Interrupt</b> - * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b> - * - \ref Sn_IR_CON : <b>CON Interrupt</b> - */ - static inline uint32_t Sn_IR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ - static inline uint32_t Sn_SR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered. - */ - static inline uint32_t Sn_PORT(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ - static inline uint32_t Sn_DHAR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ - static inline uint32_t Sn_DIPR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP clientmode, it configures the listen port number of TCP serverbefore CONNECT command. - * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ - static inline uint32_t Sn_DPORT(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ - static inline uint32_t Sn_MSSR(uint8_t N) - { - return _W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -static inline uint32_t Sn_TOS(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -static inline uint32_t Sn_TTL(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -static inline uint32_t Sn_RXBUF_SIZE(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -static inline uint32_t Sn_TXBUF_SIZE(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -static inline uint32_t Sn_TX_FSR(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -static inline uint32_t Sn_TX_RD(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -static inline uint32_t Sn_TX_WR(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * Socket n RX Write Pointer (@ref Sn_RX_WR)and Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -static inline uint32_t Sn_RX_RSR(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -static inline uint32_t Sn_RX_RD(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -static inline uint32_t Sn_RX_WR(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -static inline uint32_t Sn_IMR(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ - static inline uint32_t Sn_FRAG(uint8_t N) - { - return _W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); - } - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -static inline uint32_t Sn_KPALVTR(uint8_t N) -{ - return _W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3); -} - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -const uint8_t MR_RST = 0x80; - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -const uint8_t MR_WOL = 0x20; - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -const uint8_t MR_PB = 0x10; - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -const uint8_t MR_PPPOE = 0x08; - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -const uint8_t MR_FARP = 0x02; - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -const uint8_t IR_CONFLICT = 0x80; - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -const uint8_t IR_UNREACH = 0x40; - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -const uint8_t IR_PPPoE = 0x20; - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -const uint8_t IR_MP = 0x10; - - -/* PHYCFGR register value */ -const uint8_t PHYCFGR_RST = (uint8_t)~(1<<7); //< For PHY reset, must operate AND mask. -const uint8_t PHYCFGR_OPMD = (1<<6); // Configre PHY with OPMDC value -const uint8_t PHYCFGR_OPMDC_ALLA = (7<<3); -const uint8_t PHYCFGR_OPMDC_PDOWN = (6<<3); -const uint8_t PHYCFGR_OPMDC_NA = (5<<3); -const uint8_t PHYCFGR_OPMDC_100FA = (4<<3); -const uint8_t PHYCFGR_OPMDC_100F = (3<<3); -const uint8_t PHYCFGR_OPMDC_100H = (2<<3); -const uint8_t PHYCFGR_OPMDC_10F = (1<<3); -const uint8_t PHYCFGR_OPMDC_10H = (0<<3); -const uint8_t PHYCFGR_DPX_FULL = (1<<2); -const uint8_t PHYCFGR_DPX_HALF = (0<<2); -const uint8_t PHYCFGR_SPD_100 = (1<<1); -const uint8_t PHYCFGR_SPD_10 = (0<<1); -const uint8_t PHYCFGR_LNK_ON = (1<<0); -const uint8_t PHYCFGR_LNK_OFF = (0<<0); - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -const uint8_t IM_IR7 = 0x80; - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -const uint8_t IM_IR6 = 0x40; - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -const uint8_t IM_IR5 = 0x20; - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -const uint8_t IM_IR4 = 0x10; - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -const uint8_t Sn_MR_MULTI = 0x80; - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -const uint8_t Sn_MR_BCASTB = 0x40; - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref _RTR_. - */ -const uint8_t Sn_MR_ND = 0x20; - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -const uint8_t Sn_MR_UCASTB = 0x10; - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -const uint8_t Sn_MR_MACRAW = 0x04; - -//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -const uint8_t Sn_MR_UDP = 0x02; - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -const uint8_t Sn_MR_TCP = 0x01; - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -const uint8_t Sn_MR_CLOSE = 0x00; - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -const uint8_t Sn_MR_MFEN = Sn_MR_MULTI; - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -const uint8_t Sn_MR_MMB = Sn_MR_ND; - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -const uint8_t Sn_MR_MIP6B = Sn_MR_UCASTB; - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -const uint8_t Sn_MR_MC = Sn_MR_ND; - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -const uint8_t SOCK_STREAM = Sn_MR_TCP; - -/** - * @brief For Berkeley Socket API - */ -const uint8_t SOCK_DGRAM = Sn_MR_UDP; - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * <table> - * <tr> <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td> </tr> - * <tr> <td>Sn_MR_CLOSE (000)</td> <td></td> </tr> - * <tr> <td>Sn_MR_TCP (001)</td> <td>SOCK_INIT (0x13)</td> </tr> - * <tr> <td>Sn_MR_UDP (010)</td> <td>SOCK_UDP (0x22)</td> </tr> - * <tr> <td>S0_MR_MACRAW (100)</td> <td>SOCK_MACRAW (0x02)</td> </tr> - * </table> - */ -const uint8_t Sn_CR_OPEN = 0x01; - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (\ref Sn_MR(P3:P0) = \ref Sn_MR_TCP). - * In this mode, Socket n operates as a TCP serverand waits for connection-request (SYN packet) from any TCP client - * The @ref Sn_SR changes the state from \ref SOCK_INIT to \ref SOCKET_LISTEN. - * When a TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the @ref Sn_IR(0) becomes - * But when a TCP clientconnection request is failed, @ref Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -const uint8_t Sn_CR_LISTEN = 0x02; - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to <b>TCP server</b>configured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as <b>TCP client</b> - */ -const uint8_t Sn_CR_CONNECT = 0x04; - -/** - * @brief Send closing request in TCP mode - * @details Regardless of <b>TCP server</b>or <b>TCP client</b> the DISCON command processes the disconnect-process (b>Active close</b>or <b>Passive close</b>.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (\ref Sn_IR(3)='1') and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -const uint8_t Sn_CR_DISCON = 0x08; - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -const uint8_t Sn_CR_CLOSE = 0x10; - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -const uint8_t Sn_CR_SEND = 0x20; - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -const uint8_t Sn_CR_SEND_MAC = 0x21; - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -const uint8_t Sn_CR_SEND_KEEP = 0x22; - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -const uint8_t Sn_CR_RECV = 0x40; - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -const uint8_t Sn_IR_SENDOK = 0x10; - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -const uint8_t Sn_IR_TIMEOUT = 0x08; - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -const uint8_t Sn_IR_RECV = 0x04; - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -const uint8_t Sn_IR_DISCON = 0x02; - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -const uint8_t Sn_IR_CON = 0x01; - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\n - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -const uint8_t SOCK_CLOSED = 0x00; - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\n - * It is changed to @ref SOCK_INIT when @ref Sn_MR(P[3:0]) = 001 and OPEN command is ordered.\n - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -const uint8_t SOCK_INIT = 0x13; - -/** - * @brief Listen state - * @details This indicates Socket n is operating as <b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer <b>TCP client</b>.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO @ref Sn_IR(TIMEOUT) = '1') is occurred. - */ -const uint8_t SOCK_LISTEN = 0x14; - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = '1') is occurred. - */ -const uint8_t SOCK_SYNSENT = 0x15; - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout (@ref Sn_IR[TIMEOUT] = '1') is occurred. - */ -const uint8_t SOCK_SYNRECV = 0x16; - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the <b>TCP SERVER</b>processed the SYN packet from the <b>TCP CLIENT</b>during @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -const uint8_t SOCK_ESTABLISHED = 0x17; - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -const uint8_t SOCK_FIN_WAIT = 0x18; - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -const uint8_t SOCK_CLOSING = 0x1A; - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -const uint8_t SOCK_TIME_WAIT = 0x1B; - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -const uint8_t SOCK_CLOSE_WAIT = 0x1C; - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout(@ref Sn_IR[TIMEOUT] = '1') is occurred. - */ -const uint8_t SOCK_LAST_ACK = 0x1D; - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(@ref Sn_MR(P[3:0]) = '010').\n - * It changes to SOCK_UDP when @ref Sn_MR(P[3:0]) = '010' and @ref Sn_CR_OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -const uint8_t SOCK_UDP = 0x22; - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -const uint8_t SOCK_MACRAW = 0x42; - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -static inline void WIZCHIP_CRITICAL_ENTER() {} - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -static inline void WIZCHIP_CRITICAL_EXIT() { } - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, const uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -static inline void setMR(uint8_t mr) -{ - WIZCHIP_WRITE(MR, mr); -} - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -static inline uint8_t getMR() -{ - return WIZCHIP_READ(MR); -} - - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -static inline void setGAR(const uint8_t *gar) -{ - WIZCHIP_WRITE_BUF(GAR, gar, 4); -} - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -static inline void getGAR(uint8_t *gar) -{ - WIZCHIP_READ_BUF(GAR, gar, 4); -} - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -static inline void setSUBR(const uint8_t *subr) -{ - WIZCHIP_WRITE_BUF(SUBR, subr, 4); -} - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -static inline void getSUBR(uint8_t* subr) -{ - WIZCHIP_READ_BUF(SUBR, subr, 4); -} - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -static inline void setSHAR(const uint8_t *shar) -{ - WIZCHIP_WRITE_BUF(SHAR, shar, 6); -} - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -static inline void getSHAR(uint8_t *shar) -{ - WIZCHIP_READ_BUF(SHAR, shar, 6); -} - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -static inline void setSIPR(const uint8_t *sipr) -{ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4); -} - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -static inline void getSIPR(uint8_t *sipr) -{ - WIZCHIP_READ_BUF(SIPR, sipr, 4); -} - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -static inline void setINTLEVEL(uint16_t intlevel) -{ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); -} - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -static inline uint16_t getINTLEVEL() -{ - const uint8_t msb = WIZCHIP_READ(INTLEVEL); - return ((uint16_t)msb << 8) | WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL, 1)); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -static inline void setIR(uint8_t ir) -{ - WIZCHIP_WRITE(IR, (ir & 0xF0)); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -static inline uint8_t getIR() -{ - return WIZCHIP_READ(IR) & 0xF0; -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref _IMR_ register - * @param (uint8_t)imr Value to set @ref _IMR_ register. - * @sa getIMR() - */ -static inline void setIMR(uint8_t imr) -{ - WIZCHIP_WRITE(_IMR_, imr); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref _IMR_ register - * @return uint8_t. Value of @ref _IMR_ register. - * @sa setIMR() - */ -static inline uint8_t getIMR() -{ - return WIZCHIP_READ(_IMR_); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -static inline void setSIR(uint8_t sir) -{ - WIZCHIP_WRITE(SIR, sir); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -static inline uint8_t getSIR() -{ - return WIZCHIP_READ(SIR); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -static inline void setSIMR(uint8_t simr) -{ - WIZCHIP_WRITE(SIMR, simr); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -static inline uint8_t getSIMR() -{ - return WIZCHIP_READ(SIMR); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref _RTR_ register - * @param (uint16_t)rtr Value to set @ref _RTR_ register. - * @sa getRTR() - */ -static inline void setRTR(uint16_t rtr) -{ - WIZCHIP_WRITE(_RTR_, (uint8_t)(rtr >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref _RTR_ register - * @return uint16_t. Value of @ref _RTR_ register. - * @sa setRTR() - */ -static inline uint16_t getRTR() -{ - const uint8_t msb = WIZCHIP_READ(_RTR_); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_, 1)); -} - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref _RCR_ register - * @param (uint8_t)rcr Value to set @ref _RCR_ register. - * @sa getRCR() - */ -static inline void setRCR(uint8_t rcr) -{ - WIZCHIP_WRITE(_RCR_, rcr); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref _RCR_ register - * @return uint8_t. Value of @ref _RCR_ register. - * @sa setRCR() - */ -static inline uint8_t getRCR() -{ - return WIZCHIP_READ(_RCR_); -} - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -static inline void setPTIMER(uint8_t ptimer) -{ - WIZCHIP_WRITE(PTIMER, ptimer); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -static inline uint8_t getPTIMER() -{ - return WIZCHIP_READ(PTIMER); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -static inline void setPMAGIC(uint8_t pmagic) -{ - WIZCHIP_WRITE(PMAGIC, pmagic); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -static inline uint8_t getPMAGIC() -{ - return WIZCHIP_READ(PMAGIC); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -static inline void setPHAR(const uint8_t *phar) -{ - WIZCHIP_WRITE_BUF(PHAR, phar, 6); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHAR address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -static inline void getPHAR(uint8_t *phar) -{ - WIZCHIP_READ_BUF(PHAR, phar, 6); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -static inline void setPSID(uint16_t psid) -{ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -static inline uint16_t getPSID() -{ - const uint8_t msb = WIZCHIP_READ(PSID); - return ((uint16_t)msb << 8) | WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -static inline void setPMRU(uint16_t pmru) -{ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -static inline uint16_t getPMRU() -{ - const uint8_t msb = WIZCHIP_READ(PMRU); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU, 1)); -} - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -static inline void getUIPR(uint8_t *uipr) -{ - WIZCHIP_READ_BUF(UIPR, uipr, 4); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -static inline uint16_t getUPORTR() -{ - const uint8_t msb = WIZCHIP_READ(UPORTR); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR, 1)); -} - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -static inline void setPHYCFGR(uint8_t phycfgr) -{ - WIZCHIP_WRITE(PHYCFGR, phycfgr); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -static inline uint8_t getPHYCFGR() -{ - return WIZCHIP_READ(PHYCFGR); -} - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -static inline uint8_t getVERSIONR() -{ - return WIZCHIP_READ(VERSIONR); -} - -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -static inline void setSn_MR(uint8_t sn, uint8_t mr) -{ - WIZCHIP_WRITE(Sn_MR(sn), mr); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -static inline uint8_t getSn_MR(uint8_t sn) -{ - return WIZCHIP_READ(Sn_MR(sn)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -static inline void setSn_CR(uint8_t sn, uint8_t cr) -{ - WIZCHIP_WRITE(Sn_CR(sn), cr); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -static inline uint8_t getSn_CR(uint8_t sn) -{ - return WIZCHIP_READ(Sn_CR(sn)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -static inline void setSn_IR(uint8_t sn, uint8_t ir) -{ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -static inline uint8_t getSn_IR(uint8_t sn) -{ - return WIZCHIP_READ(Sn_IR(sn)) & 0x1F; -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -static inline void setSn_IMR(uint8_t sn, uint8_t imr) -{ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -static inline uint8_t getSn_IMR(uint8_t sn) -{ - return WIZCHIP_READ(Sn_IMR(sn)) & 0x1F; -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_SR. - */ -static inline uint8_t getSn_SR(uint8_t sn) -{ - return WIZCHIP_READ(Sn_SR(sn)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -static inline void setSn_PORT(uint8_t sn, uint16_t port) -{ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn), 1), (uint8_t) port); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -static inline uint16_t getSn_PORT(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_PORT(sn)); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn), 1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -static inline void setSn_DHAR(uint8_t sn, const uint8_t *dhar) -{ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -static inline void getSn_DHAR(uint8_t sn, uint8_t *dhar) -{ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -static inline void setSn_DIPR(uint8_t sn, const uint8_t *dipr) -{ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa setSn_DIPR() - */ -static inline void getSn_DIPR(uint8_t sn, uint8_t *dipr) -{ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -static inline void setSn_DPORT(uint8_t sn, uint16_t dport) -{ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn), 1), (uint8_t) dport); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -static inline uint16_t getSn_DPORT(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_DPORT(sn)); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -static inline void setSn_MSSR(uint8_t sn, uint16_t mss) -{ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn), 1), (uint8_t) mss); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -static inline uint16_t getSn_MSSR(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_MSSR(sn)); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn), 1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -static inline void setSn_TOS(uint8_t sn, uint8_t tos) -{ - WIZCHIP_WRITE(Sn_TOS(sn), tos); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -static inline uint8_t getSn_TOS(uint8_t sn) -{ - return WIZCHIP_READ(Sn_TOS(sn)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -static inline void setSn_TTL(uint8_t sn, uint8_t ttl) -{ - WIZCHIP_WRITE(Sn_TTL(sn), ttl); -} - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -static inline uint8_t getSn_TTL(uint8_t sn) -{ - return WIZCHIP_READ(Sn_TTL(sn)); -} - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -static inline void setSn_RXBUF_SIZE(uint8_t sn, uint8_t rxbufsize) -{ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize); -} - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -static inline uint8_t getSn_RXBUF_SIZE(uint8_t sn) -{ - return WIZCHIP_READ(Sn_RXBUF_SIZE(sn)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -static inline void setSn_TXBUF_SIZE(uint8_t sn, uint8_t txbufsize) -{ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -static inline uint8_t getSn_TXBUF_SIZE(uint8_t sn) -{ - return WIZCHIP_READ(Sn_TXBUF_SIZE(sn)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -static inline uint16_t getSn_TX_RD(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_TX_RD(sn)); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -static inline void setSn_TX_WR(uint8_t sn, uint16_t txwr) -{ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn), 1), (uint8_t) txwr); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -static inline uint16_t getSn_TX_WR(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_TX_WR(sn)); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)); -} - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -static inline void setSn_RX_RD(uint8_t sn, uint16_t rxrd) -{ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -static inline uint16_t getSn_RX_RD(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_RX_RD(sn)); - return ((uint16_t)msb << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn), 1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -static inline uint16_t getSn_RX_WR(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_RX_WR(sn)); - return ((uint16_t)msb << 8) | WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn), 1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -static inline void setSn_FRAG(uint8_t sn, uint16_t frag) -{ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >> 8)); - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -static inline uint16_t getSn_FRAG(uint8_t sn) -{ - const uint8_t msb = WIZCHIP_READ(Sn_FRAG(sn)); - return ((uint16_t)msb << 8) | WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)); -} - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -static inline void setSn_KPALVTR(uint8_t sn, uint8_t kpalvt) -{ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt); -} - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -static inline uint8_t getSn_KPALVTR(uint8_t sn) -{ - return WIZCHIP_READ(Sn_KPALVTR(sn)); -} - -////////////////////////////////////// - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Socket_register_access_function - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -static inline uint16_t getSn_RxMAX(uint8_t sn) -{ - return ((uint16_t)getSn_RXBUF_SIZE(sn)) << 10; -} - -/** - * @brief Socket_register_access_function - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -static inline uint16_t getSn_TxMAX(uint8_t sn) -{ - return ((uint16_t)getSn_TXBUF_SIZE(sn)) << 10; -} - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -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 - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes. - * This function is being called by recv() also. - * - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/src/Network2/W5500/Wiznet/Ethernet/WizSpi.cpp b/src/Network2/W5500/Wiznet/Ethernet/WizSpi.cpp deleted file mode 100644 index 9a695791..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/WizSpi.cpp +++ /dev/null @@ -1,434 +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 1 // use peripheral DMA controller -#define USE_DMAC 0 // use general DMA controller - -#if USE_PDC -#include "pdc/pdc.h" -#endif - -#if USE_DMAC -#include "dmac/dmac.h" -#endif - -#include "matrix/matrix.h" - -// SPI data rate. I tried 60MHz and we got some data corruption when uploading files, so I reduced it to 40MHz. -// 2018-01-11: We have now received one report of data corruption at 40MHz, so reduced this to 30MHz -const uint32_t SpiClockFrequency = 30000000; -const unsigned int SpiPeripheralChannelId = 0; // we use NPCS0 as the slave select signal - -// Functions called by the W5500 module to transfer data to/from the W5500 via SPI - -#if USE_PDC -static Pdc *spi_pdc; - -static inline void spi_rx_dma_enable() -{ - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); // we have to transmit in order to receive -} - -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 | PERIPH_PTCR_TXTDIS); // we have to transmit in order to receive -} - -static inline void spi_tx_dma_disable() -{ - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS); -} - -static bool spi_dma_check_rx_complete() -{ - return pdc_read_rx_counter(spi_pdc) == 0; -} - -static void spi_tx_dma_setup(const uint8_t *buf, uint32_t length) -{ - pdc_packet_t pdc_spi_packet; - pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); - pdc_spi_packet.ul_size = length; - pdc_tx_init(spi_pdc, &pdc_spi_packet, nullptr); -} - -static void spi_rx_dma_setup(uint8_t *buf, uint32_t length) -{ - pdc_packet_t pdc_spi_packet; - pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); - pdc_spi_packet.ul_size = length; - pdc_rx_init(spi_pdc, &pdc_spi_packet, nullptr); - pdc_tx_init(spi_pdc, &pdc_spi_packet, nullptr); // we have to transmit in order to receive -} - -#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(); -} - -#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 receive 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]); - pinMode(APIN_SPI_SS0, OUTPUT_HIGH); // use manual SS control - - 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 transmit buffer empty, returning true if timed out - static inline bool waitForTxReady() - { - uint32_t timeout = SPI_TIMEOUT; - while ((SPI->SPI_SR & SPI_SR_TDRE) == 0) - { - 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->SPI_SR & SPI_SR_TXEMPTY) == 0) - { - 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->SPI_SR & SPI_SR_RDRF) == 0) - { - 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(W5500SsPin, LOW); - (void)SPI->SPI_RDR; // clear receive register - } - - // Set the SS pin high again - void ReleaseSS() - { - waitForTxEmpty(); - digitalWrite(W5500SsPin, HIGH); - } - - // Send the 3-byte address and control bits. On return there may be data still being received. - void SendAddress(uint32_t addr) - { - 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; - } - } - } - } - - // Read a single byte. Called after sending the 3-byte address. - uint8_t ReadByte() - { - (void)SPI->SPI_RDR; - if (!waitForTxEmpty()) - { - while ((SPI->SPI_SR & SPI_SR_RDRF) != 0) - { - (void)SPI->SPI_RDR; // clear previous data - } - SPI->SPI_TDR = 0x000000FF; - if (!waitForRxReady()) - { - return (uint8_t)SPI->SPI_RDR; - } - } - return 0; - } - - // Write a single byte. Called after sending the address. - void WriteByte(uint8_t b) - { - const uint32_t dOut = b; - if (!waitForTxReady()) - { - SPI->SPI_TDR = dOut; - } - } - - // Read some data - spi_status_t ReadBurst(uint8_t* rx_data, size_t len) - { - if (len != 0) - { - if (waitForTxEmpty()) - { - return SPI_ERROR_TIMEOUT; - } - - while ((SPI->SPI_SR & SPI_SR_RDRF) != 0) - { - (void)SPI->SPI_RDR; // clear previous data - } - -#if USE_PDC - spi_rx_dma_setup(rx_data, len); - spi_rx_dma_enable(); - while (pdc_read_tx_counter(spi_pdc) != 0) { } - uint32_t timeout = SPI_TIMEOUT; - while (!spi_dma_check_rx_complete() && timeout != 0) - { - --timeout; - } - spi_rx_dma_disable(); - if (timeout == 0) - { - return SPI_ERROR_TIMEOUT; - } -#else - const uint32_t dOut = 0x000000FF; - SPI->SPI_TDR = dOut; // send first byte - while (--len != 0) - { - // Wait for receive data available and transmit buffer empty - uint32_t timeout = SPI_TIMEOUT + 1; - do - { - if (--timeout == 0) - { - return SPI_ERROR_TIMEOUT; - } - } - while ((SPI->SPI_SR & (SPI_SR_RDRF | SPI_SR_TDRE)) != (SPI_SR_RDRF | SPI_SR_TDRE)); - - const uint32_t din = SPI->SPI_RDR; // get data from receive register - SPI->SPI_TDR = dOut; // write to transmit register immediately - *rx_data++ = (uint8_t)din; - } - - if (waitForRxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - *rx_data++ = (uint8_t)SPI->SPI_RDR; // Get last byte from receive register -#endif - } - return SPI_OK; - } - - // Send some data - spi_status_t SendBurst(const uint8_t* tx_data, size_t len) - { -#if USE_PDC - spi_tx_dma_setup(tx_data, len); - spi_tx_dma_enable(); - while (pdc_read_tx_counter(spi_pdc) != 0) { } - spi_tx_dma_disable(); -#else - for (uint32_t i = 0; i < len; ++i) - { - uint32_t dOut = (uint32_t)*tx_data++; - if (waitForTxReady()) - { - return SPI_ERROR_TIMEOUT; - } - - SPI->SPI_TDR = dOut; // write to transmit register - (void)SPI->SPI_RDR; - } -#endif - return SPI_OK; - } - -} // end namespace - -// End diff --git a/src/Network2/W5500/Wiznet/Ethernet/WizSpi.h b/src/Network2/W5500/Wiznet/Ethernet/WizSpi.h deleted file mode 100644 index eeea6be4..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/WizSpi.h +++ /dev/null @@ -1,26 +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/spi.h" - -namespace WizSpi -{ - void Init(); - void Stop(); - void AssertSS(); - void ReleaseSS(); - void SendAddress(uint32_t addr); - 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); -} - -#endif /* SRC_DUETNG_DUETETHERNET_ETHERNET3_UTILITY_WIZSPI_H_ */ diff --git a/src/Network2/W5500/Wiznet/Ethernet/socketlib.cpp b/src/Network2/W5500/Wiznet/Ethernet/socketlib.cpp deleted file mode 100644 index 1ca60309..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/socketlib.cpp +++ /dev/null @@ -1,745 +0,0 @@ -//***************************************************************************** -// -//! \file socket.c -//! \brief SOCKET APIs Implements file. -//! \details SOCKET APIs like as Berkeley Socket APIs. -//! \version 1.0.3 -//! \date 2013/10/21 -//! \par Revision history -//! <2015/02/05> Notice -//! The version history is not updated after this point. -//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. -//! >> https://github.com/Wiznet/ioLibrary_Driver -//! <2014/05/01> V1.0.3. Refer to M20140501 -//! 1. Implicit type casting -> Explicit type casting. -//! 2. replace 0x01 with PACK_REMAINED in recvfrom() -//! 3. Validation a destination ip in connect() & sendto(): -//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. -//! Copy 4 byte addr value into temporary uint32 variable and then compares it. -//! <2013/12/20> V1.0.2 Refer to M20131220 -//! Remove Warning. -//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". -//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -#include <Network2/W5500/Wiznet/Ethernet/socketlib.h> - -//#define _SOCKET_DEBUG_ - -#ifdef _SOCKET_DEBUG_ -extern "C" void debugPrintf(const char *fmt, ...); -extern "C" void delay(uint32_t); -# define DEBUG_PRINTF(...) debugPrintf(__VA_ARGS__) -#else -# define DEBUG_PRINTF(_fmt, ...) -#endif - -#define SOCK_ANY_PORT_NUM 0xC000 - -static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; -static uint16_t sock_io_mode = 0; -static uint16_t sock_is_sending = 0; - -static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; - -uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; - -#define CHECK_SOCKMODE(mode) \ - do{ \ - if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ - }while(0); \ - -#define CHECK_SOCKINIT() \ - do{ \ - if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ - }while(0); \ - -#define CHECK_SOCKDATA() \ - do{ \ - if(len == 0) return SOCKERR_DATALEN; \ - }while(0); \ - -void ExecCommand(uint8_t sn, uint8_t cmd) -{ - setSn_CR(sn, cmd); - while(getSn_CR(sn) != 0) { } -} - -int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) -{ - switch(protocol) - { - case Sn_MR_TCP: - { - uint32_t taddr; - getSIPR((uint8_t*)&taddr); - if (taddr == 0) - { - return SOCKERR_SOCKINIT; - } - } - break; - - case Sn_MR_UDP: - case Sn_MR_MACRAW: - break; - - default: - return SOCKERR_SOCKMODE; - } - - if ((flag & 0x04) != 0) - { - return SOCKERR_SOCKFLAG; - } - - if (flag != 0) - { - switch(protocol) - { - case Sn_MR_TCP: - if ((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK)) == 0) - { - return SOCKERR_SOCKFLAG; - } - break; - case Sn_MR_UDP: - if (flag & SF_IGMP_VER2) - { - if ((flag & SF_MULTI_ENABLE) == 0) - { - return SOCKERR_SOCKFLAG; - } - } - if (flag & SF_UNI_BLOCK) - { - if ((flag & SF_MULTI_ENABLE) == 0) - { - return SOCKERR_SOCKFLAG; - } - } - break; - default: - break; - } - } - close(sn); - setSn_MR(sn, (protocol | (flag & 0xF0))); - if (port == 0) - { - port = sock_any_port++; - if (sock_any_port == 0xFFF0) - { - sock_any_port = SOCK_ANY_PORT_NUM; - } - } - setSn_PORT(sn,port); - ExecCommand(sn, Sn_CR_OPEN); - - // release the previous sock_io_mode - sock_io_mode &= ~(1 <<sn); - sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); - sock_is_sending &= ~(1<<sn); - sock_remained_size[sn] = 0; - sock_pack_info[sn] = PACK_COMPLETED; - while(getSn_SR(sn) == SOCK_CLOSED) { } - return (int8_t)sn; -} - -int8_t close(uint8_t sn) -{ - ExecCommand(sn, Sn_CR_CLOSE); - - // Clear all interrupt of the socket - setSn_IR(sn, 0xFF); - // Release the sock_io_mode of socket n. - sock_io_mode &= ~(1<<sn); - sock_is_sending &= ~(1<<sn); - sock_remained_size[sn] = 0; - sock_pack_info[sn] = 0; - while(getSn_SR(sn) != SOCK_CLOSED) { } - return SOCK_OK; -} - -int8_t listen(uint8_t sn) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKINIT(); - ExecCommand(sn, Sn_CR_LISTEN); - while(getSn_SR(sn) != SOCK_LISTEN) - { - close(sn); - return SOCKERR_SOCKCLOSED; - } - return SOCK_OK; -} - -int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKINIT(); - { - uint32_t taddr = ((uint32_t)addr[0] & 0x000000FF); - taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF); - taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF); - taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF); - if (taddr == 0xFFFFFFFF || taddr == 0) - { - return SOCKERR_IPINVALID; - } - } - - if (port == 0) - { - return SOCKERR_PORTZERO; - } - setSn_DIPR(sn,addr); - setSn_DPORT(sn,port); - ExecCommand(sn, Sn_CR_CONNECT); - if (sock_io_mode & (1<<sn)) - { - return SOCK_BUSY; - } - while(getSn_SR(sn) != SOCK_ESTABLISHED) - { - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - - if (getSn_SR(sn) == SOCK_CLOSED) - { - return SOCKERR_SOCKCLOSED; - } - } - - return SOCK_OK; -} - -int8_t disconnect(uint8_t sn) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - ExecCommand(sn, Sn_CR_DISCON); - - sock_is_sending &= ~(1<<sn); - if (sock_io_mode & (1<<sn)) - { - return SOCK_BUSY; - } - while(getSn_SR(sn) != SOCK_CLOSED) - { - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - close(sn); - return SOCKERR_TIMEOUT; - } - } - return SOCK_OK; -} - -void disconnectNoWait(uint8_t sn) -{ - ExecCommand(sn, Sn_CR_DISCON); -} - -int32_t send(uint8_t sn, uint8_t * buf, uint16_t len) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - uint8_t tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) - { - return SOCKERR_SOCKSTATUS; - } - if ( sock_is_sending & (1<<sn) ) - { - tmp = getSn_IR(sn); - if (tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - sock_is_sending &= ~(1<<sn); - } - else if(tmp & Sn_IR_TIMEOUT) - { - close(sn); - return SOCKERR_TIMEOUT; - } - else - { - return SOCK_BUSY; - } - } - uint16_t freesize = getSn_TxMAX(sn); - if (len > freesize) - { - len = freesize; // check size not to exceed MAX size. - } - while(1) - { - freesize = getSn_TX_FSR(sn); - tmp = getSn_SR(sn); - if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) - { - close(sn); - return SOCKERR_SOCKSTATUS; - } - if ( (sock_io_mode & (1<<sn)) && (len > freesize) ) - { - return SOCK_BUSY; - } - if (len <= freesize) - { - break; - } - DEBUG_PRINTF("Socket %u need %u free %u\n", sn, len, freesize); - } - wiz_send_data(sn, buf, len); - - ExecCommand(sn, Sn_CR_SEND); - sock_is_sending |= (1 << sn); - return (int32_t)len; -} - - -int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - - uint16_t recvsize = getSn_RxMAX(sn); - if (recvsize < len) - { - len = recvsize; - } - - while(1) - { - recvsize = getSn_RX_RSR(sn); - const uint8_t tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED) - { - if (tmp == SOCK_CLOSE_WAIT) - { - if (recvsize != 0) - { - break; - } - else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) - { - close(sn); - return SOCKERR_SOCKSTATUS; - } - } - else - { - close(sn); - return SOCKERR_SOCKSTATUS; - } - } - if ((sock_io_mode & (1<<sn)) && (recvsize == 0)) - { - return SOCK_BUSY; - } - if (recvsize != 0) - { - break; - } - }; - - if (recvsize < len) - { - len = recvsize; - } - wiz_recv_data(sn, buf, len); - ExecCommand(sn, Sn_CR_RECV); - - return (int32_t)len; -} - -int32_t sendto(uint8_t sn, const uint8_t * buf, uint16_t len, const uint8_t * addr, uint16_t port) -{ - switch(getSn_MR(sn) & 0x0F) - { - case Sn_MR_UDP: - case Sn_MR_MACRAW: - break; - default: - return SOCKERR_SOCKMODE; - } - - CHECK_SOCKDATA(); - uint32_t taddr = ((uint32_t)addr[0]) & 0x000000FF; - taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF); - taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF); - taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF); - if (taddr == 0) - { - return SOCKERR_IPINVALID; - } - if (port == 0) - { - return SOCKERR_PORTZERO; - } - const uint8_t tmp = getSn_SR(sn); - if (tmp != SOCK_MACRAW && tmp != SOCK_UDP) - { - return SOCKERR_SOCKSTATUS; - } - - setSn_DIPR(sn,addr); - setSn_DPORT(sn,port); - uint16_t freesize = getSn_TxMAX(sn); - if (len > freesize) - { - len = freesize; // check size not to exceed MAX size. - } - - while(1) - { - freesize = getSn_TX_FSR(sn); - if (getSn_SR(sn) == SOCK_CLOSED) - { - return SOCKERR_SOCKCLOSED; - } - if ( (sock_io_mode & (1<<sn)) && (len > freesize) ) - { - return SOCK_BUSY; - } - if (len <= freesize) - { - break; - } - DEBUG_PRINTF("Socket %u need %u free %u\n", sn, len, freesize); - }; - - wiz_send_data(sn, buf, len); - ExecCommand(sn, Sn_CR_SEND); - - while(1) - { - const uint8_t tmp = getSn_IR(sn); - if (tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - break; - } - else if(tmp & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - DEBUG_PRINTF("Socket %u waiting for send to complete, IR=%02x\n", sn, tmp); -#ifdef _SOCKET_DEBUG_ - delay(10); // to avoid too many messages -#endif - } - return (int32_t)len; -} - - -int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) -{ - const uint8_t mr = getSn_MR(sn); - switch(mr & 0x0F) - { - case Sn_MR_UDP: - case Sn_MR_MACRAW: - break; - default: - return SOCKERR_SOCKMODE; - } - - CHECK_SOCKDATA(); - uint16_t pack_len=0; - if (sock_remained_size[sn] == 0) - { - while(1) - { - pack_len = getSn_RX_RSR(sn); - if (getSn_SR(sn) == SOCK_CLOSED) - { - return SOCKERR_SOCKCLOSED; - } - if ( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) - { - return SOCK_BUSY; - } - if (pack_len != 0) - { - break; - } - } - } - - switch (mr & 0x07) - { - case Sn_MR_UDP : - if (sock_remained_size[sn] == 0) - { - uint8_t head[8]; - wiz_recv_data(sn, head, 8); - ExecCommand(sn, Sn_CR_RECV); - - // Read peer's IP address, port number & packet length - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - *port = head[4]; - *port = (*port << 8) + head[5]; - sock_remained_size[sn] = head[6]; - sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7]; - sock_pack_info[sn] = PACK_FIRST; - } - if (len < sock_remained_size[sn]) - { - pack_len = len; - } - else - { - pack_len = sock_remained_size[sn]; - } - len = pack_len; - // - // Need to packet length check (default 1472) - // - wiz_recv_data(sn, buf, pack_len); // data copy. - break; - - case Sn_MR_MACRAW : - if (sock_remained_size[sn] == 0) - { - uint8_t head[8]; - wiz_recv_data(sn, head, 2); - ExecCommand(sn, Sn_CR_RECV); - - // Read peer's IP address, port number & packet length - sock_remained_size[sn] = head[0]; - sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1]; - if (sock_remained_size[sn] > 1514) - { - close(sn); - return SOCKFATAL_PACKLEN; - } - sock_pack_info[sn] = PACK_FIRST; - } - if (len < sock_remained_size[sn]) - { - pack_len = len; - } - else - { - pack_len = sock_remained_size[sn]; - } - wiz_recv_data(sn,buf,pack_len); - break; - - default: - wiz_recv_ignore(sn, pack_len); // data copy. - sock_remained_size[sn] = pack_len; - break; - } - ExecCommand(sn, Sn_CR_RECV); - - sock_remained_size[sn] -= pack_len; - if (sock_remained_size[sn] != 0) - { - sock_pack_info[sn] |= PACK_REMAINED; - } - else - { - sock_pack_info[sn] = PACK_COMPLETED; - } - return (int32_t)pack_len; -} - - -int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) -{ - switch(cstype) - { - case CS_SET_IOMODE: - { - const uint8_t tmp = *((uint8_t*)arg); - if (tmp == SOCK_IO_NONBLOCK) - { - sock_io_mode |= (1<<sn); - } - else if (tmp == SOCK_IO_BLOCK) - { - sock_io_mode &= ~(1<<sn); - } - else - { - return SOCKERR_ARG; - } - } - break; - case CS_GET_IOMODE: - *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); - break; - case CS_GET_MAXTXBUF: - *((uint16_t*)arg) = getSn_TxMAX(sn); - break; - case CS_GET_MAXRXBUF: - *((uint16_t*)arg) = getSn_RxMAX(sn); - break; - case CS_CLR_INTERRUPT: - if ((*(uint8_t*)arg) > SIK_ALL) - { - return SOCKERR_ARG; - } - setSn_IR(sn, *(uint8_t*)arg); - break; - case CS_GET_INTERRUPT: - *((uint8_t*)arg) = getSn_IR(sn); - break; - case CS_SET_INTMASK: - if ((*(uint8_t*)arg) > SIK_ALL) - { - return SOCKERR_ARG; - } - setSn_IMR(sn, *(uint8_t*)arg); - break; - case CS_GET_INTMASK: - *((uint8_t*)arg) = getSn_IMR(sn); - break; - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg) -{ - switch(sotype) - { - case SO_TTL: - setSn_TTL(sn,*(uint8_t*)arg); - break; - case SO_TOS: - setSn_TOS(sn,*(uint8_t*)arg); - break; - case SO_MSS: - setSn_MSSR(sn,*(uint16_t*)arg); - break; - case SO_DESTIP: - setSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - setSn_DPORT(sn, *(uint16_t*)arg); - break; - case SO_KEEPALIVESEND: - CHECK_SOCKMODE(Sn_MR_TCP); - if (getSn_KPALVTR(sn) != 0) - { - return SOCKERR_SOCKOPT; - } - setSn_CR(sn, Sn_CR_SEND_KEEP); - while(getSn_CR(sn) != 0) - { - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - } - break; - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - setSn_KPALVTR(sn,*(uint8_t*)arg); - break; - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg) -{ - switch(sotype) - { - case SO_FLAG: - *(uint8_t*)arg = getSn_MR(sn) & 0xF0; - break; - case SO_TTL: - *(uint8_t*) arg = getSn_TTL(sn); - break; - case SO_TOS: - *(uint8_t*) arg = getSn_TOS(sn); - break; - case SO_MSS: - *(uint8_t*) arg = getSn_MSSR(sn); - break; - case SO_DESTIP: - getSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - *(uint16_t*) arg = getSn_DPORT(sn); - break; - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint16_t*) arg = getSn_KPALVTR(sn); - break; - case SO_SENDBUF: - *(uint16_t*) arg = getSn_TX_FSR(sn); - break; - case SO_RECVBUF: - *(uint16_t*) arg = getSn_RX_RSR(sn); - break; - case SO_STATUS: - *(uint8_t*) arg = getSn_SR(sn); - break; - case SO_REMAINSIZE: - if (getSn_MR(sn) == Sn_MR_TCP) - { - *(uint16_t*)arg = getSn_RX_RSR(sn); - } - else - { - *(uint16_t*)arg = sock_remained_size[sn]; - } - break; - case SO_PACKINFO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint8_t*)arg = sock_pack_info[sn]; - break; - default: - return SOCKERR_SOCKOPT; - } - return SOCK_OK; -} - -// End diff --git a/src/Network2/W5500/Wiznet/Ethernet/socketlib.h b/src/Network2/W5500/Wiznet/Ethernet/socketlib.h deleted file mode 100644 index 623b768c..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/socketlib.h +++ /dev/null @@ -1,487 +0,0 @@ -//***************************************************************************** -// -//! \file socket.h -//! \brief SOCKET APIs Header file. -//! \details SOCKET APIs like as berkeley socket api. -//! \version 1.0.2 -//! \date 2013/10/21 -//! \par Revision history -//! <2015/02/05> Notice -//! The version history is not updated after this point. -//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. -//! >> https://github.com/Wiznet/ioLibrary_Driver -//! <2014/05/01> V1.0.2. Refer to M20140501 -//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED -//! 2. Add the comment as zero byte udp data reception in getsockopt(). -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -/** - * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs - * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. - * But there is a little bit of difference. - * @details - * <b> Comparison between WIZnet and Berkeley SOCKET APIs </b> - * <table> - * <tr> <td><b>API</b></td> <td><b>WIZnet</b></td> <td><b>Berkeley</b></td> </tr> - * <tr> <td>socket()</td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>bind()</b></td> <td>X</td> <td>O</td> </tr> - * <tr> <td><b>listen()</b></td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>connect()</b></td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>accept()</b></td> <td>X</td> <td>O</td> </tr> - * <tr> <td><b>recv()</b></td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>send()</b></td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>recvfrom()</b></td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>sendto()</b></td> <td>O</td> <td>O</td> </tr> - * <tr> <td><b>closesocket()</b></td> <td>O<br>close() & disconnect()</td> <td>O</td> </tr> - * </table> - * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, - * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, - * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n - * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. - * When the listen SOCKET accepts a connection request from a client, it keeps listening. - * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n - * Following figure shows network flow diagram by Berkeley SOCKET API. - * @image html Berkeley_SOCKET.jpg "<Berkeley SOCKET API>" - * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n - * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, - * it is changed in order to communicate with the client. - * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n - * If there're many listen SOCKET with same listen port number and a client requests a connection, - * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n - * Following figure shows network flow diagram by WIZnet SOCKET API. - * @image html WIZnet_SOCKET.jpg "<WIZnet SOCKET API>" - */ -#ifndef _SOCKET_H_ -#define _SOCKET_H_ - -#include <Network2/W5500/Wiznet/Ethernet/wizchip_conf.h> - -#define SOCKET uint8_t ///< SOCKET type define for legacy driver - -#define SOCK_OK 1 ///< Result is OK about socket process. -#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. -#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. - -#define SOCK_ERROR 0 -#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number -#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option -#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized or SIPR is Zero IP address when Sn_MR_TCP -#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. -#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. -#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag -#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. -#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. -#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero -#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address -#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred -#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. -#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. - -#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. - -/* - * SOCKET FLAG - */ -#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In @ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet -#define SF_IGMP_VER2 (Sn_MR_MC) ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. -#define SF_TCP_NODELAY (Sn_MR_ND) ///< In @ref Sn_MR_TCP, Use to nodelayed ack. -#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In @ref Sn_MR_UDP, Enable multicast mode. - -#if _WIZCHIP_ == 5500 - #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In @ref Sn_MR_UDP or @ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 - #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In @ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 - #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In @ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 - #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 -#endif - -//A201505 : For W5300 -#if _WIZCHIP_ == 5300 - #define SF_TCP_ALIGN 0x02 ///< Valid only \ref Sn_MR_TCP and W5300, refer to \ref Sn_MR_ALIGN -#endif - -#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). - -/* - * UDP & MACRAW Packet Infomation - */ -#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. (When W5300, This flag can be applied) -#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. (When W5300, This flag can be applied) -#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. (When W5300, This flag can be applied) -//A20150601 : For Integrating with W5300 -#define PACK_FIFOBYTE 0x02 ///< Valid only W5300, It indicate to have read already the Sn_RX_FIFOR. -// - -/** - * @ingroup WIZnet_socket_APIs - * @brief Open a socket. - * @details Initializes the socket with 'sn' passed as parameter and open. - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. - * @param port Port number to be bined. - * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n - * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. - * @sa Sn_MR - * - * @return @b Success : The socket number @b 'sn' passed as parameter\n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n - * @ref SOCKERR_SOCKFLAG - Invaild socket flag. - */ -int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Close a socket. - * @details It closes the socket with @b'sn' passed as parameter. - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number - */ -int8_t close(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Listen to a connection request from a client. - * @details It is listening to a connection request from a client. - * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n - * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. - */ -int8_t listen(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to connect a server. - * @details It requests connection to the server with destination IP address and port number passed as parameter.\n - * @note It is valid only in TCP client mode. - * In block io mode, it does not return until connection is completed. - * In Non-block io mode, it return @ref SOCK_BUSY immediately. - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Invalid socket mode\n - * @ref SOCKERR_SOCKINIT - Socket is not initialized\n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n - * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n - */ -int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to disconnect a connection socket. - * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. - * @note It is valid only in TCP server or client mode. \n - * In block io mode, it does not return until disconnection is completed. \n - * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n - - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int8_t disconnect(uint8_t sn); - -void disconnectNoWait(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Send data to the connected peer in TCP socket. - * @details It is used to send outgoing data to the connected socket. - * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n - * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param buf Pointer buffer containing data to be sent. - * @param len The byte length of data in buf. - * @return @b Success : The sent data size \n - * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t send(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive data from the connected peer. - * @details It is used to read incoming data from the connected socket.\n - * It waits for data as much as the application wants to receive. - * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n - * In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n - * In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * @return @b Success : The real received data size \n - * @b Fail :\n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. - * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n - * Even if the connectionless socket has been previously connected to a specific address, - * the address and port number parameters override the destination address for that particular datagram only. - * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>. - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param buf Pointer buffer to send outgoing data. - * @param len The byte length of data in buf. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : The sent data size \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t sendto(uint8_t sn, const uint8_t * buf, uint16_t len, const uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive datagram of UDP or MACRAW - * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n - * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. - * This function can divide to received the packet data. - * On the MACRAW SOCKET, the addr and port parameters are ignored. - * @note In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer - * In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * When the received packet size <= len, receives data as packet sized. - * When others, receives data as len. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * It is valid only when the first call recvfrom for receiving the packet. - * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * @param port Pointer variable of destination port number. - * It is valid only when the first call recvform for receiving the packet. -* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * - * @return @b Success : This function return real received data size for success.\n - * @b Fail : @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKBUSY - Socket is busy. - */ -int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); - - -///////////////////////////// -// SOCKET CONTROL & OPTION // -///////////////////////////// -#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). -#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). - -/** - * @defgroup DATA_TYPE DATA TYPE - */ - -/** - * @ingroup DATA_TYPE - * @brief The kind of Socket Interrupt. - * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() - */ -typedef enum -{ - SIK_CONNECTED = (1 << 0), ///< connected - SIK_DISCONNECTED = (1 << 1), ///< disconnected - SIK_RECEIVED = (1 << 2), ///< data received - SIK_TIMEOUT = (1 << 3), ///< timeout occurred - SIK_SENT = (1 << 4), ///< send ok - //M20150410 : Remove the comma of last member - //SIK_ALL = 0x1F, ///< all interrupt - SIK_ALL = 0x1F ///< all interrupt -}sockint_kind; - -/** - * @ingroup DATA_TYPE - * @brief The type of @ref ctlsocket(). - */ -typedef enum -{ - CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK - CS_GET_IOMODE, ///< get socket IO mode - CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory - CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory - CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind - CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind -#if _WIZCHIP_ > 5100 - CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind, Not supported in W5100 - CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind, Not supported in W5100 -#endif -}ctlsock_type; - - -/** - * @ingroup DATA_TYPE - * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() - */ -typedef enum -{ - SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to <I>flag</I> in @ref socket(). - SO_TTL, ///< Set TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) - SO_TOS, ///< Set TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) - SO_MSS, ///< Set MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) - SO_DESTIP, ///< Set the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) - SO_DESTPORT, ///< Set the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) -#if _WIZCHIP_ != 5100 - SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode, Not supported in W5100 - #if _WIZCHIP_ > 5200 - SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode, Not supported in W5100, W5200 - #endif -#endif - SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() - SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() - SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() - SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. - SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. -}sockopt_type; - -/** - * @ingroup WIZnet_socket_APIs - * @brief Control socket. - * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. - * Refer to @ref ctlsock_type. - * @param sn socket number - * @param cstype type of control socket. refer to @ref ctlsock_type. - * @param arg Data type and value is determined according to @ref ctlsock_type. \n - * <table> - * <tr> <td> @b cstype </td> <td> @b data type</td><td>@b value</td></tr> - * <tr> <td> @ref CS_SET_IOMODE \n @ref CS_GET_IOMODE </td> <td> uint8_t </td><td>@ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK</td></tr> - * <tr> <td> @ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF </td> <td> uint16_t </td><td> 0 ~ 16K </td></tr> - * <tr> <td> @ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK </td> <td> @ref sockint_kind </td><td> @ref SIK_CONNECTED, etc. </td></tr> - * </table> - * @return @b Success @ref SOCK_OK \n - * @b fail @ref SOCKERR_ARG - Invalid argument\n - */ -int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief set socket options - * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. - * - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to <I>sotype</I>. \n - * <table> - * <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr> - * <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> - * <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> - * <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr> - * <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr> - * <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> - * <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr> - * <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> - * </table> - * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n - */ -int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief get socket options - * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to <I>sotype</I>. \n - * <table> - * <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr> - * <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr> - * <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> - * <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr> - * <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr> - * <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> </td></tr> - * <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> - * <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> - * <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> - * <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr> - * <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr> - * <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr> - * </table> - * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * @note - * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n - * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, - * This means the zero byte UDP data(UDP Header only) received. - */ -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/Network2/W5500/Wiznet/Ethernet/wizchip_conf.cpp b/src/Network2/W5500/Wiznet/Ethernet/wizchip_conf.cpp deleted file mode 100644 index 1bf27419..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/wizchip_conf.cpp +++ /dev/null @@ -1,457 +0,0 @@ -//****************************************************************************/ -//! -//! \file wizchip_conf.c -//! \brief WIZCHIP Config Header File. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2015/02/05> Notice -//! The version history is not updated after this point. -//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. -//! >> https://github.com/Wiznet/ioLibrary_Driver -//! <2014/05/01> V1.0.1 Refer to M20140501 -//! 1. Explicit type casting in wizchip_bus_readdata() & wizchip_bus_writedata() -// Issued by Mathias ClauBen. -//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* -//! For remove the warning when pointer type size is not 32bit. -//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//*****************************************************************************/ -//A20140501 : for use the type - ptrdiff_t - -#include <Network2/W5500/Wiznet/Ethernet/wizchip_conf.h> -#include <Network2/W5500/Wiznet/Ethernet/WizSpi.h> -#include <cstddef> -#include <cstring> - -/** - * @\ref WIZCHIP instance data - */ - -static uint8_t _DNS_[4]; // DNS server ip address -static dhcp_mode _DHCP_; // DHCP mode -static const char WizchipId[6] = "w5500"; - -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) -{ - switch(cwtype) - { - case CW_RESET_WIZCHIP: - wizchip_sw_reset(); - break; - case CW_INIT_WIZCHIP: - { - uint8_t* ptmp[2] = {0,0}; - if (arg != 0) - { - ptmp[0] = (uint8_t*)arg; - ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; - } - return wizchip_init(ptmp[0], ptmp[1]); - } - case CW_CLR_INTERRUPT: - wizchip_clrinterrupt(*((intr_kind*)arg)); - break; - case CW_GET_INTERRUPT: - *((intr_kind*)arg) = wizchip_getinterrupt(); - break; - case CW_SET_INTRMASK: - wizchip_setinterruptmask(*((intr_kind*)arg)); - break; - case CW_GET_INTRMASK: - *((intr_kind*)arg) = wizchip_getinterruptmask(); - break; - case CW_SET_INTRTIME: - setINTLEVEL(*(uint16_t*)arg); - break; - case CW_GET_INTRTIME: - *(uint16_t*)arg = getINTLEVEL(); - break; - case CW_GET_ID: - memcpy(arg, WizchipId, sizeof(WizchipId)); - break; - case CW_RESET_PHY: - wizphy_reset(); - break; - case CW_SET_PHYCONF: - wizphy_setphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYCONF: - wizphy_getphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYSTATUS: - break; - case CW_SET_PHYPOWMODE: - return wizphy_setphypmode(*(uint8_t*)arg); - case CW_GET_PHYPOWMODE: - { - uint8_t tmp = wizphy_getphypmode(); - if ((int8_t)tmp == -1) - { - return -1; - } - *(uint8_t*)arg = tmp; - } - break; - case CW_GET_PHYLINK: - { - uint8_t tmp = wizphy_getphylink(); - if ((int8_t)tmp == -1) - { - return -1; - } - *(uint8_t*)arg = tmp; - } - break; - default: - return -1; - } - return 0; -} - - -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) -{ - switch(cntype) - { - case CN_SET_NETINFO: - wizchip_setnetinfo((wiz_NetInfo*)arg); - break; - case CN_GET_NETINFO: - wizchip_getnetinfo((wiz_NetInfo*)arg); - break; - case CN_SET_NETMODE: - return wizchip_setnetmode(*(netmode_type*)arg); - case CN_GET_NETMODE: - *(netmode_type*)arg = wizchip_getnetmode(); - break; - case CN_SET_TIMEOUT: - wizchip_settimeout((wiz_NetTimeout*)arg); - break; - case CN_GET_TIMEOUT: - wizchip_gettimeout((wiz_NetTimeout*)arg); - break; - default: - return -1; - } - return 0; -} - -void wizchip_sw_reset(void) -{ - uint8_t gw[4], sn[4], sip[4]; - uint8_t mac[6]; - getSHAR(mac); - getGAR(gw); getSUBR(sn); getSIPR(sip); - setMR(MR_RST); - getMR(); // for delay - setSHAR(mac); - setGAR(gw); - setSUBR(sn); - setSIPR(sip); -} - -int8_t wizchip_init(const uint8_t* txsize, const uint8_t* rxsize) -{ - WizSpi::Init(); - wizchip_sw_reset(); - if (txsize != nullptr) - { - int8_t tmp = 0; - for (uint8_t i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - { - tmp += txsize[i]; - if (tmp > 16) - { - return -1; - } - } - for (uint8_t i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - { - setSn_TXBUF_SIZE(i, txsize[i]); - } - } - if (rxsize != nullptr) - { - int8_t tmp = 0; - for (uint8_t i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - { - tmp += rxsize[i]; - if (tmp > 16) - { - return -1; - } - } - - for (uint8_t i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - { - setSn_RXBUF_SIZE(i, rxsize[i]); - } - } - return 0; -} - -void wizchip_clrinterrupt(intr_kind intr) -{ - setIR((uint8_t)intr); - setSIR((uint8_t)((uint16_t)intr >> 8)); -} - -intr_kind wizchip_getinterrupt(void) -{ - const uint8_t ir = getIR(); - const uint8_t sir = getSIR(); - const uint16_t ret = ((uint16_t)sir << 8) | ir; - return (intr_kind)ret; -} - -void wizchip_setinterruptmask(intr_kind intr) -{ - setIMR((uint8_t)intr); - setSIMR((uint8_t)((uint16_t)intr >> 8)); -} - -intr_kind wizchip_getinterruptmask(void) -{ - const uint8_t imr = getIMR(); - const uint8_t simr = getSIMR(); - const uint16_t ret = ((uint16_t)simr << 8) | imr; - return (intr_kind)ret; -} - -int8_t wizphy_getphylink(void) -{ - return (getPHYCFGR() & PHYCFGR_LNK_ON) ? PHY_LINK_ON : PHY_LINK_OFF; -} - -int8_t wizphy_getphypmode(void) -{ - return (getPHYCFGR() & PHYCFGR_OPMDC_PDOWN) ? PHY_POWER_DOWN : PHY_POWER_NORM; -} - -void wizphy_reset(void) -{ - uint8_t tmp = getPHYCFGR(); - tmp &= PHYCFGR_RST; - setPHYCFGR(tmp); - tmp = getPHYCFGR(); - tmp |= ~PHYCFGR_RST; - setPHYCFGR(tmp); -} - -void wizphy_setphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - if (phyconf->by == PHY_CONFBY_SW) - { - tmp |= PHYCFGR_OPMD; - } - else - { - tmp &= ~PHYCFGR_OPMD; - } - if (phyconf->mode == PHY_MODE_AUTONEGO) - { - tmp |= PHYCFGR_OPMDC_ALLA; - } - else - { - if (phyconf->duplex == PHY_DUPLEX_FULL) - { - if (phyconf->speed == PHY_SPEED_100) - { - tmp |= PHYCFGR_OPMDC_100F; - } - else - { - tmp |= PHYCFGR_OPMDC_10F; - } - } - else - { - if (phyconf->speed == PHY_SPEED_100) - { - tmp |= PHYCFGR_OPMDC_100H; - } - else - { - tmp |= PHYCFGR_OPMDC_10H; - } - } - } - setPHYCFGR(tmp); - wizphy_reset(); -} - -void wizphy_getphyconf(wiz_PhyConf* phyconf) -{ - const uint8_t tmp = getPHYCFGR(); - phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_ALLA: - case PHYCFGR_OPMDC_100FA: - phyconf->mode = PHY_MODE_AUTONEGO; - break; - default: - phyconf->mode = PHY_MODE_MANUAL; - break; - } - - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_100H: - phyconf->speed = PHY_SPEED_100; - break; - default: - phyconf->speed = PHY_SPEED_10; - break; - } - - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_10F: - phyconf->duplex = PHY_DUPLEX_FULL; - break; - default: - phyconf->duplex = PHY_DUPLEX_HALF; - break; - } -} - -void wizphy_getphystat(wiz_PhyConf* phyconf) -{ - const uint8_t tmp = getPHYCFGR(); - phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; - phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; -} - -int8_t wizphy_setphypmode(uint8_t pmode) -{ - uint8_t tmp = getPHYCFGR(); - if ((tmp & PHYCFGR_OPMD)== 0) - { - return -1; - } - tmp &= ~PHYCFGR_OPMDC_ALLA; - if (pmode == PHY_POWER_DOWN) - { - tmp |= PHYCFGR_OPMDC_PDOWN; - } - else - { - tmp |= PHYCFGR_OPMDC_ALLA; - } - setPHYCFGR(tmp); - wizphy_reset(); - - tmp = getPHYCFGR(); - if (pmode == PHY_POWER_DOWN) - { - if (tmp & PHYCFGR_OPMDC_PDOWN) - { - return 0; - } - } - else - { - if (tmp & PHYCFGR_OPMDC_ALLA) - { - return 0; - } - } - return -1; -} - - -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) -{ - setSHAR(pnetinfo->mac); - setGAR(pnetinfo->gw); - setSUBR(pnetinfo->sn); - setSIPR(pnetinfo->ip); - _DNS_[0] = pnetinfo->dns[0]; - _DNS_[1] = pnetinfo->dns[1]; - _DNS_[2] = pnetinfo->dns[2]; - _DNS_[3] = pnetinfo->dns[3]; - _DHCP_ = pnetinfo->dhcp; -} - -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) -{ - getSHAR(pnetinfo->mac); - getGAR(pnetinfo->gw); - getSUBR(pnetinfo->sn); - getSIPR(pnetinfo->ip); - pnetinfo->dns[0]= _DNS_[0]; - pnetinfo->dns[1]= _DNS_[1]; - pnetinfo->dns[2]= _DNS_[2]; - pnetinfo->dns[3]= _DNS_[3]; - pnetinfo->dhcp = _DHCP_; -} - -int8_t wizchip_setnetmode(netmode_type netmode) -{ - if (netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) - { - return -1; - } - uint8_t tmp = getMR(); - tmp |= (uint8_t)netmode; - setMR(tmp); - return 0; -} - -netmode_type wizchip_getnetmode(void) -{ - return (netmode_type) getMR(); -} - -void wizchip_settimeout(wiz_NetTimeout* nettime) -{ - setRCR(nettime->retry_cnt); - setRTR(nettime->time_100us); -} - -void wizchip_gettimeout(wiz_NetTimeout* nettime) -{ - nettime->retry_cnt = getRCR(); - nettime->time_100us = getRTR(); -} - -// End diff --git a/src/Network2/W5500/Wiznet/Ethernet/wizchip_conf.h b/src/Network2/W5500/Wiznet/Ethernet/wizchip_conf.h deleted file mode 100644 index a69fbe47..00000000 --- a/src/Network2/W5500/Wiznet/Ethernet/wizchip_conf.h +++ /dev/null @@ -1,422 +0,0 @@ -//***************************************************************************** -// -//! \file wizchip_conf.h -//! \brief WIZCHIP Config Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2015/02/05> Notice -//! The version history is not updated after this point. -//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. -//! >> https://github.com/Wiznet/ioLibrary_Driver -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -/** - * @defgroup extra_functions 2. WIZnet Extra Functions - * - * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. - * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n - * - */ - -#ifndef _WIZCHIP_CONF_H_ -#define _WIZCHIP_CONF_H_ - -#include <stdint.h> -/** - * @brief Select WIZCHIP. - * @todo You should select one, \b 5100, \b 5200, \b 5300, \b 5500 or etc. \n\n - * ex> <code> #define \_WIZCHIP_ 5500 </code> - */ -#ifndef _WIZCHIP_ -# define _WIZCHIP_ 5500 // 5100, 5200, 5300, 5500 -#endif - -#define _WIZCHIP_IO_MODE_NONE_ 0x0000 -#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ -#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ -//#define _WIZCHIP_IO_MODE_IIC_ 0x0400 -//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 - -#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ -#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ - -#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ -#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ - - -#define _WIZCHIP_ID_ "W5500" - -/** - * @brief Define interface mode. \n - * @todo Should select interface mode as chip. - * - @ref \_WIZCHIP_IO_MODE_SPI_ \n - * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * - @ref \_WIZCHIP_IO_MODE_BUS_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n - * - Others will be defined in future. \n\n - * ex> <code> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ </code> - * - */ -#ifndef _WIZCHIP_IO_MODE_ - //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ -#endif - -typedef uint8_t iodata_t; - -#include <Network2/W5500/Wiznet/Ethernet/W5500/w5500.h> - -#ifndef _WIZCHIP_IO_MODE_ - #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" -#endif - -/** - * @brief Define I/O base address when BUS IF mode. - * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, - * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n - * ex> <code> #define \_WIZCHIP_IO_BASE_ 0x00008000 </code> - */ -#ifndef _WIZCHIP_IO_BASE_ -# define _WIZCHIP_IO_BASE_ 0x00000000 // 0x8000 -#endif - -#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_ - #ifndef _WIZCHIP_IO_BASE_ - #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." - #endif -#endif - -#define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independent socket of @b WIZCHIP - - -/******************************************************** -* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. -*********************************************************/ - -/** - * @ingroup DATA_TYPE - * WIZCHIP control type enumeration used in @ref ctlwizchip(). - */ -enum ctlwizchip_type -{ - CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly - CW_INIT_WIZCHIP, ///< Initializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. - CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP - CW_CLR_INTERRUPT, ///< Clears interrupt - CW_SET_INTRMASK, ///< Masks interrupt - CW_GET_INTRMASK, ///< Get interrupt mask - CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_ID, ///< Gets WIZCHIP name. - - CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5500 - CW_SET_PHYCONF, ///< When PHY configured by internal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 - CW_GET_PHYCONF, ///< Get PHY operation mode in internal register. Valid Only W5500 - CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5500 - CW_SET_PHYPOWMODE, ///< Set PHY power mode as normal and down when PHYSTATUS.OPMD == 1. Valid Only W5500 - CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal, Valid Only W5100, W5200 - CW_GET_PHYLINK ///< Get PHY Link status, Valid Only W5100, W5200 -}; - -/** - * @ingroup DATA_TYPE - * Network control type enumration used in @ref ctlnetwork(). - */ -enum ctlnetwork_type -{ - CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo - CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo - CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. - CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. -}; - -/** - * @ingroup DATA_TYPE - * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK - * and CW_GET_INTRMASK is used in @ref ctlnetwork(). - * It can be used with OR operation. - */ -enum intr_kind -{ - IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. - - IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected - - IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreachable, No use in W5200 - - IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred - - IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt - IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt - IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt - IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt - IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 - IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 - IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 - IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 - - IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrupt -}; - -#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin -#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register -#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. -#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation -#define PHY_SPEED_10 0 ///< Link Speed 10 -#define PHY_SPEED_100 1 ///< Link Speed 100 -#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex -#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex -#define PHY_LINK_OFF 0 ///< Link Off -#define PHY_LINK_ON 1 ///< Link On -#define PHY_POWER_NORM 0 ///< PHY power normal mode -#define PHY_POWER_DOWN 1 ///< PHY power down mode - - -/** - * @ingroup DATA_TYPE - * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, - * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n - * Valid only in W5500. - */ -struct wiz_PhyConf -{ - uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW - uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO - uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 - uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL - //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN - //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF -}; - -/** - * @ingroup DATA_TYPE - * It used in setting dhcp_mode of @ref wiz_NetInfo. - */ -enum dhcp_mode -{ - NETINFO_STATIC = 1, ///< Static IP configuration by manually. - NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever -}; - -/** - * @ingroup DATA_TYPE - * Network Information for WIZCHIP - */ -struct wiz_NetInfo -{ - uint8_t mac[6]; ///< Source Mac Address - uint8_t ip[4]; ///< Source IP Address - uint8_t sn[4]; ///< Subnet Mask - uint8_t gw[4]; ///< Gateway IP Address - uint8_t dns[4]; ///< DNS server IP Address - dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP -}; - -/** - * @ingroup DATA_TYPE - * Network mode - */ -enum netmode_type -{ - NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 - NM_WAKEONLAN = (1<<5), ///< Wake On Lan - NM_PINGBLOCK = (1<<4), ///< Block ping-request - NM_PPPOE = (1<<3), ///< PPPoE mode -}; - -/** - * @ingroup DATA_TYPE - * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. - */ -struct wiz_NetTimeout -{ - uint8_t retry_cnt; ///< retry count - uint16_t time_100us; ///< time unit 100us -}; - - -/** - * @ingroup extra_functions - * @brief Controls to the WIZCHIP. - * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), - * controls interrupt & mask and so on. - * @param cwtype : Decides to the control type - * @param arg : arg type is dependent on cwtype. - * @return 0 : Success \n - * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP - */ -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); - -/** - * @ingroup extra_functions - * @brief Controls to network. - * @details Controls to network environment, mode, timeout and so on. - * @param cntype : Input. Decides to the control type - * @param arg : Inout. arg type is dependent on cntype. - * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n - * 0 : Success - */ -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); - - -/* - * The following functions are implemented for internal use. - * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). - */ - -/** - * @ingroup extra_functions - * @brief Reset WIZCHIP by softly. - */ -void wizchip_sw_reset(void); - -/** - * @ingroup extra_functions - * @brief Initializes WIZCHIP with socket buffer size - * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. - * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. - * @return 0 : succcess \n - * -1 : fail. Invalid buffer size - */ -int8_t wizchip_init(const uint8_t* txsize, const uint8_t* rxsize); - -/** - * @ingroup extra_functions - * @brief Clear Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_clrinterrupt(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt of WIZCHIP. - * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterrupt(void); - -/** - * @ingroup extra_functions - * @brief Mask or Unmask Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_setinterruptmask(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt mask of WIZCHIP. - * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterruptmask(void); - -int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 -int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 - -void wizphy_reset(void); ///< Reset phy. Valid only in W5500 - -/** - * @ingroup extra_functions - * @brief Set the phy information for WIZCHIP without power mode - * @param phyconf : @ref wiz_PhyConf - */ -void wizphy_setphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy configuration information. - * @param phyconf : @ref wiz_PhyConf - */ -void wizphy_getphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy status. - * @param phyconf : @ref wiz_PhyConf - */ -void wizphy_getphystat(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 - * @param pmode Settig value of power down mode. - */ -int8_t wizphy_setphypmode(uint8_t pmode); - -/** -* @ingroup extra_functions - * @brief Set the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); - -/** - * @ingroup extra_functions - * @brief Get the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); - -/** - * @ingroup extra_functions - * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. - * @param pnetinfo Value of network mode. Refer to @ref netmode_type. - */ -int8_t wizchip_setnetmode(netmode_type netmode); - -/** - * @ingroup extra_functions - * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. - * @return Value of network mode. Refer to @ref netmode_type. - */ -netmode_type wizchip_getnetmode(void); - -/** - * @ingroup extra_functions - * @brief Set retry time value(@ref _RTR_) and retry count(@ref _RCR_). - * @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission. - * @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_settimeout(wiz_NetTimeout* nettime); - -/** - * @ingroup extra_functions - * @brief Get retry time value(@ref _RTR_) and retry count(@ref _RCR_). - * @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission. - * @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_gettimeout(wiz_NetTimeout* nettime); - -#endif // _WIZCHIP_CONF_H_ diff --git a/src/Network2/W5500/Wiznet/Internet/DHCP/dhcp.cpp b/src/Network2/W5500/Wiznet/Internet/DHCP/dhcp.cpp deleted file mode 100644 index e8de7ae9..00000000 --- a/src/Network2/W5500/Wiznet/Internet/DHCP/dhcp.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.c -//! \brief DHCP APIs implement file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Optimize code -//! 2. Add reg_dhcp_cbfunc() -//! 3. Add DHCP_stop() -//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() -//! 5. Don't care system endian -//! 6. Add comments -//! <2012/12/26> V1.1.1 -//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include <Network2/W5500/Wiznet/Ethernet/socketlib.h> -#include <Network2/W5500/Wiznet/Internet/DHCP/dhcp.h> -#include <cstring> - -/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ - -//#define _DHCP_DEBUG_ - -#ifdef _DHCP_DEBUG_ -extern "C" void debugPrintf(const char *fmt, ...); -# define DEBUG_PRINTF(...) debugPrintf(__VA_ARGS__) -#else -# define DEBUG_PRINTF(_fmt, ...) -#endif - -/* DHCP state machine. */ -#define STATE_DHCP_INIT 0 ///< Initialize -#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER -#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK -#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased -#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP -#define STATE_DHCP_RELEASE 5 ///< No use -#define STATE_DHCP_STOP 6 ///< Stop processing DHCP - -#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG -#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG - -/* DHCP message OP code */ -#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG -#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG - -/* DHCP message type */ -#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG -#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG -#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG -#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG -#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG -#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG -#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use -#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use - -#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG -#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG - -#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG -#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG -#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG - -#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time - -#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG -#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG - -/* - * @brief DHCP option and value (cf. RFC1533) - */ -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 -}; - -/* - * @brief DHCP message format - */ -typedef struct { - uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY - uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB - uint8_t hlen; ///< @ref DHCP_HLENETHERNET - uint8_t hops; ///< @ref DHCP_HOPS - uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction. - uint16_t secs; ///< @ref DHCP_SECS - uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST - uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever - uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server - uint8_t siaddr[4]; ///< No use - uint8_t giaddr[4]; ///< No use - uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero - uint8_t sname[64]; ///< No use - uint8_t file[128]; ///< No use - uint8_t OPT[OPT_SIZE]; ///< Option -} RIP_MSG; - - - -uint8_t DHCP_SOCKET; // Socket number for DHCP - -uint8_t DHCP_SIP[4]; // DHCP Server IP address - -// Network information from DHCP Server -uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address -uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP -uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP -uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP -uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP - - -int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state -int8_t dhcp_retry_count = 0; - -uint32_t dhcp_lease_time = INFINITE_LEASETIME; -volatile uint32_t dhcp_tick_1s = 0; // unit 1 second -uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; - -uint32_t DHCP_XID; // Any number - -static RIP_MSG dhcpMessageBuffer; -RIP_MSG* const pDHCPMSG = &dhcpMessageBuffer; // Buffer pointer for DHCP processing - -char HOST_NAME[16] = DCHP_HOST_NAME; -uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. - -/* The default callback function */ -void default_ip_assign(void); -void default_ip_update(void); -void default_ip_conflict(void); - -/* Callback handler */ -void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */ -void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */ -void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */ - -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - - -/* send DISCOVER message to DHCP server */ -void send_DHCP_DISCOVER(void); - -/* send REQEUST message to DHCP server */ -void send_DHCP_REQUEST(void); - -/* send DECLINE message to DHCP server */ -void send_DHCP_DECLINE(void); - -/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ -bool check_DHCP_leasedIP(void); - -/* check the timeout in DHCP process */ -DhcpRunResult check_DHCP_timeout(void); - -/* Initialize to timeout process. */ -void reset_DHCP_timeout(void); - -/* Parse message as OFFER and ACK and NACK from DHCP server.*/ -int8_t parseDHCPMSG(void); - -/* The default handler of ip assign first */ -void default_ip_assign(void) -{ - setSIPR(DHCP_allocated_ip); - setSUBR(DHCP_allocated_sn); - setGAR (DHCP_allocated_gw); -} - -/* The default handler of ip chaged */ -void default_ip_update(void) -{ - /* WIZchip Software Reset */ - setMR(MR_RST); - getMR(); // for delay - default_ip_assign(); - setSHAR(DHCP_CHADDR); -} - -/* The default handler of ip chaged */ -void default_ip_conflict(void) -{ - // WIZchip Software Reset - setMR(MR_RST); - getMR(); // for delay - setSHAR(DHCP_CHADDR); -} - -/* register the call back func. */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) -{ - dhcp_ip_assign = default_ip_assign; - dhcp_ip_update = default_ip_update; - dhcp_ip_conflict = default_ip_conflict; - if(ip_assign) { dhcp_ip_assign = ip_assign; } - if(ip_update) { dhcp_ip_update = ip_update; } - if(ip_conflict) { dhcp_ip_conflict = ip_conflict; } -} - -/* make the common DHCP message */ -void makeDHCPMSG(void) -{ - uint8_t bk_mac[6]; - getSHAR(bk_mac); - pDHCPMSG->op = DHCP_BOOTREQUEST; - pDHCPMSG->htype = DHCP_HTYPE10MB; - pDHCPMSG->hlen = DHCP_HLENETHERNET; - pDHCPMSG->hops = DHCP_HOPS; - uint8_t* ptmp = (uint8_t*)(&pDHCPMSG->xid); - *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); - *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); - *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8); - *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0); - pDHCPMSG->secs = DHCP_SECS; - ptmp = (uint8_t*)(&pDHCPMSG->flags); - *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); - *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); - - pDHCPMSG->ciaddr[0] = 0; - pDHCPMSG->ciaddr[1] = 0; - pDHCPMSG->ciaddr[2] = 0; - pDHCPMSG->ciaddr[3] = 0; - - pDHCPMSG->yiaddr[0] = 0; - pDHCPMSG->yiaddr[1] = 0; - pDHCPMSG->yiaddr[2] = 0; - pDHCPMSG->yiaddr[3] = 0; - - pDHCPMSG->siaddr[0] = 0; - pDHCPMSG->siaddr[1] = 0; - pDHCPMSG->siaddr[2] = 0; - pDHCPMSG->siaddr[3] = 0; - - pDHCPMSG->giaddr[0] = 0; - pDHCPMSG->giaddr[1] = 0; - pDHCPMSG->giaddr[2] = 0; - pDHCPMSG->giaddr[3] = 0; - - pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; - pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; - pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; - pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; - pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; - pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; - - for (size_t i = 6; i < 16; i++) - { - pDHCPMSG->chaddr[i] = 0; - } - for (size_t i = 0; i < 64; i++) - { - pDHCPMSG->sname[i] = 0; - } - for (size_t i = 0; i < 128; i++) - { - pDHCPMSG->file[i] = 0; - } - - // MAGIC_COOKIE - pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); - pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); - pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); - pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; -} - -/* SEND DHCP DISCOVER */ -void send_DHCP_DISCOVER(void) -{ - makeDHCPMSG(); - - size_t k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DISCOVER; - - // Client identifier - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname - size_t i; - for (i = 0 ; HOST_NAME[i] != 0; i++) - { - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - } - pDHCPMSG->OPT[k - (i+1)] = i; // length of hostname - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x06; // length of request - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) - { - pDHCPMSG->OPT[i] = 0; - } - - // send broadcasting packet - uint8_t ip[4]; - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - - DEBUG_PRINTF("> Send DHCP_DISCOVER\n"); - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); - DEBUG_PRINTF("Sent\n"); -} - -/* SEND DHCP REQUEST */ -void send_DHCP_REQUEST(void) -{ - - makeDHCPMSG(); - - uint8_t ip[4]; - if (dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) - { - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; - pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; - pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; - pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; - ip[0] = DHCP_SIP[0]; - ip[1] = DHCP_SIP[1]; - ip[2] = DHCP_SIP[2]; - ip[3] = DHCP_SIP[3]; - } - else - { - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - } - - size_t k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_REQUEST; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - if (ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) - { - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - } - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // length of hostname - size_t i; - for (i = 0 ; HOST_NAME[i] != 0; i++) - { - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - } - pDHCPMSG->OPT[k - (i+1)] = i; // length of hostname - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x08; - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = performRouterDiscovery; - pDHCPMSG->OPT[k++] = staticRoute; - pDHCPMSG->OPT[k++] = endOption; - - for (size_t i = k; i < OPT_SIZE; i++) - { - pDHCPMSG->OPT[i] = 0; - } - - DEBUG_PRINTF("> Send DHCP_REQUEST\n"); - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* SEND DHCP DHCPDECLINE */ -void send_DHCP_DECLINE(void) -{ - makeDHCPMSG(); - - size_t k = 4; // beacaue MAGIC_COOKIE already made by makeDHCPMSG() - - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DECLINE; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - - pDHCPMSG->OPT[k++] = endOption; - - for (size_t i = k; i < OPT_SIZE; i++) - { - pDHCPMSG->OPT[i] = 0; - } - - //send broadcasting packet - uint8_t ip[4]; - ip[0] = 0xFF; - ip[1] = 0xFF; - ip[2] = 0xFF; - ip[3] = 0xFF; - - DEBUG_PRINTF("\n> Send DHCP_DECLINE\n"); - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* PARSE REPLY pDHCPMSG */ -int8_t parseDHCPMSG(void) -{ - uint8_t type = 0; - uint16_t len; - if ((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) - { - if (len > sizeof(RIP_MSG)) - { - len = sizeof(RIP_MSG); - } - - uint8_t svr_addr[6]; - uint16_t svr_port; - len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); - - DEBUG_PRINTF("DHCP message : %d.%d.%d.%d(%d) %d received. \n", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3],svr_port, len); - - if (svr_port == DHCP_SERVER_PORT) - { - // compare mac address - if ( (pDHCPMSG->chaddr[0] == DHCP_CHADDR[0]) && (pDHCPMSG->chaddr[1] == DHCP_CHADDR[1]) - && (pDHCPMSG->chaddr[2] == DHCP_CHADDR[2]) && (pDHCPMSG->chaddr[3] == DHCP_CHADDR[3]) - && (pDHCPMSG->chaddr[4] == DHCP_CHADDR[4]) && (pDHCPMSG->chaddr[5] == DHCP_CHADDR[5]) - ) - { - const uint8_t *p = (uint8_t *)(&pDHCPMSG->op); - p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) - const uint8_t * const e = p + (len - 240); - - while (p < e) - { - switch (*p ) - { - case endOption : - p = e; // for break while(p < e) - break; - case padOption : - p++; - break; - case dhcpMessageType : - p++; - p++; - type = *p++; - break; - case subnetMask : - p++; - p++; - DHCP_allocated_sn[0] = *p++; - DHCP_allocated_sn[1] = *p++; - DHCP_allocated_sn[2] = *p++; - DHCP_allocated_sn[3] = *p++; - break; - case routersOnSubnet : - { - p++; - const uint8_t opt_len = *p++; - DHCP_allocated_gw[0] = *p++; - DHCP_allocated_gw[1] = *p++; - DHCP_allocated_gw[2] = *p++; - DHCP_allocated_gw[3] = *p++; - p = p + (opt_len - 4); - } - break; - case dns : - { - p++; - const uint8_t opt_len = *p++; - DHCP_allocated_dns[0] = *p++; - DHCP_allocated_dns[1] = *p++; - DHCP_allocated_dns[2] = *p++; - DHCP_allocated_dns[3] = *p++; - p = p + (opt_len - 4); - } - break; - case dhcpIPaddrLeaseTime : - { - p++; - p++; - dhcp_lease_time = *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; -#if 0 //#ifdef _DHCP_DEBUG_ - dhcp_lease_time = 10; -#endif - } - break; - case dhcpServerIdentifier : - { - p++; - p++; - DHCP_SIP[0] = *p++; - DHCP_SIP[1] = *p++; - DHCP_SIP[2] = *p++; - DHCP_SIP[3] = *p++; - } - break; - - default : - { - p++; - const uint8_t opt_len = *p++; - p += opt_len; - } - break; - } // switch - } // while - } // if - } // if - } // if - return type; -} - -DhcpRunResult DHCP_run(void) -{ - if (dhcp_state == STATE_DHCP_STOP) - { - return DhcpRunResult::DHCP_STOPPED; - } - - if (getSn_SR(DHCP_SOCKET) != SOCK_UDP) - { - socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); - } - - DhcpRunResult ret = DhcpRunResult::DHCP_RUNNING; - const uint8_t type = parseDHCPMSG(); - - switch (dhcp_state) - { - case STATE_DHCP_INIT: - DHCP_allocated_ip[0] = 0; - DHCP_allocated_ip[1] = 0; - DHCP_allocated_ip[2] = 0; - DHCP_allocated_ip[3] = 0; - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - - case STATE_DHCP_DISCOVER: - if (type == DHCP_OFFER) - { - DEBUG_PRINTF("> Receive DHCP_OFFER\n"); - DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; - DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; - DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; - DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; - - send_DHCP_REQUEST(); - dhcp_state = STATE_DHCP_REQUEST; - } - else - { - ret = check_DHCP_timeout(); - } - break; - - case STATE_DHCP_REQUEST : - if (type == DHCP_ACK) - { - DEBUG_PRINTF("> Receive DHCP_ACK\n"); - if (check_DHCP_leasedIP()) - { - // Network info assignment from DHCP - dhcp_ip_assign(); - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; - ret = DhcpRunResult::DHCP_IP_ASSIGN; - } - else - { - // IP address conflict occurred - reset_DHCP_timeout(); - dhcp_ip_conflict(); - dhcp_state = STATE_DHCP_INIT; - } - } - else if (type == DHCP_NAK) - { - DEBUG_PRINTF("> Receive DHCP_NACK\n"); - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_DISCOVER; - } - else - { - ret = check_DHCP_timeout(); - } - break; - - case STATE_DHCP_LEASED : - ret = DhcpRunResult::DHCP_IP_LEASED; - if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) - { - DEBUG_PRINTF("> Maintains the IP address \n"); - OLD_allocated_ip[0] = DHCP_allocated_ip[0]; - OLD_allocated_ip[1] = DHCP_allocated_ip[1]; - OLD_allocated_ip[2] = DHCP_allocated_ip[2]; - OLD_allocated_ip[3] = DHCP_allocated_ip[3]; - - DHCP_XID++; - - send_DHCP_REQUEST(); - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_REREQUEST; - } - break; - - case STATE_DHCP_REREQUEST : - ret = DhcpRunResult::DHCP_IP_LEASED; - if (type == DHCP_ACK) - { - dhcp_retry_count = 0; - if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] || - OLD_allocated_ip[1] != DHCP_allocated_ip[1] || - OLD_allocated_ip[2] != DHCP_allocated_ip[2] || - OLD_allocated_ip[3] != DHCP_allocated_ip[3]) - { - ret = DhcpRunResult::DHCP_IP_CHANGED; - dhcp_ip_update(); - DEBUG_PRINTF(">IP changed.\n"); - } - else - { - DEBUG_PRINTF(">IP is continued.\n"); - } - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; - } - else if (type == DHCP_NAK) - { - DEBUG_PRINTF("> Receive DHCP_NACK, Failed to maintain ip\n"); - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_DISCOVER; - } - else - { - ret = check_DHCP_timeout(); - } - break; - - default : - break; - } - - return ret; -} - -void DHCP_stop(void) -{ - close(DHCP_SOCKET); - dhcp_state = STATE_DHCP_STOP; -} - -DhcpRunResult check_DHCP_timeout(void) -{ - DhcpRunResult ret = DhcpRunResult::DHCP_RUNNING; - - if (dhcp_retry_count < MAX_DHCP_RETRY) - { - if (dhcp_tick_next < dhcp_tick_1s) - { - switch ( dhcp_state ) - { - case STATE_DHCP_DISCOVER : - DEBUG_PRINTF("<<timeout>> state : STATE_DHCP_DISCOVER\n"); - send_DHCP_DISCOVER(); - break; - - case STATE_DHCP_REQUEST : - DEBUG_PRINTF("<<timeout>> state : STATE_DHCP_REQUEST\n"); - - send_DHCP_REQUEST(); - break; - - case STATE_DHCP_REREQUEST : - DEBUG_PRINTF("<<timeout>> state : STATE_DHCP_REREQUEST\n"); - - send_DHCP_REQUEST(); - break; - - default : - break; - } - - dhcp_tick_1s = 0; - dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; - dhcp_retry_count++; - } - } - else - { // exceeded retry count - switch(dhcp_state) - { - case STATE_DHCP_DISCOVER: - dhcp_state = STATE_DHCP_INIT; - ret = DhcpRunResult::DHCP_FAILED; - break; - case STATE_DHCP_REQUEST: - case STATE_DHCP_REREQUEST: - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - default : - break; - } - reset_DHCP_timeout(); - } - return ret; -} - -bool check_DHCP_leasedIP(void) -{ - uint8_t tmp; - int32_t ret; - - //WIZchip RCR value changed for ARP Timeout count control - tmp = getRCR(); - setRCR(0x03); - - // IP conflict detection : ARP request - ARP reply - // Broadcasting ARP Request for check the IP conflict using UDP sendto() function - // TODO the following takes 620ms to time out - hanging for this long isn't very nice - ret = sendto(DHCP_SOCKET, (const uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); - - // RCR value restore - setRCR(tmp); - - if (ret == SOCKERR_TIMEOUT) - { - // UDP send Timeout occurred : allocated IP address is unique, DHCP Success - DEBUG_PRINTF("\n> Check leased IP - OK\n"); - return true; - } - else - { - // Received ARP reply or etc : IP address conflict occur, DHCP Failed - send_DHCP_DECLINE(); - - ret = dhcp_tick_1s; - //TODO can't tolerate a 1 to 2 second wait here - while((dhcp_tick_1s - ret) < 2) { } // wait for 1s over; wait to complete to send DECLINE message; - - return false; - } -} - -void DHCP_init(uint8_t s, const char *hname) -{ - strncpy(HOST_NAME, hname, sizeof(HOST_NAME)); - HOST_NAME[sizeof(HOST_NAME) - 1] = 0; - - uint8_t zeroip[4] = {0,0,0,0}; - getSHAR(DHCP_CHADDR); - DEBUG_PRINTF("MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", DHCP_CHADDR[0], DHCP_CHADDR[1], DHCP_CHADDR[2], DHCP_CHADDR[3], DHCP_CHADDR[4], DHCP_CHADDR[5]); - - if ((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) - { - // assing temporary mac address, you should be set SHAR before call this function. - DHCP_CHADDR[0] = 0x00; - DHCP_CHADDR[1] = 0x08; - DHCP_CHADDR[2] = 0xdc; - DHCP_CHADDR[3] = 0x00; - DHCP_CHADDR[4] = 0x00; - DHCP_CHADDR[5] = 0x00; - setSHAR(DHCP_CHADDR); - } - - DHCP_SOCKET = s; // SOCK_DHCP - DHCP_XID = 0x12345678; - - // WIZchip Netinfo Clear - setSIPR(zeroip); - setSIPR(zeroip); - setGAR(zeroip); - - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_INIT; -} - -/* Rset the DHCP timeout count and retry count. */ -void reset_DHCP_timeout(void) -{ - dhcp_tick_1s = 0; - dhcp_tick_next = DHCP_WAIT_TIME; - dhcp_retry_count = 0; -} - -void DHCP_time_handler(void) -{ - dhcp_tick_1s++; -} - -void getIPfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_ip[0]; - ip[1] = DHCP_allocated_ip[1]; - ip[2] = DHCP_allocated_ip[2]; - ip[3] = DHCP_allocated_ip[3]; -} - -void getGWfromDHCP(uint8_t* ip) -{ - ip[0] =DHCP_allocated_gw[0]; - ip[1] =DHCP_allocated_gw[1]; - ip[2] =DHCP_allocated_gw[2]; - ip[3] =DHCP_allocated_gw[3]; -} - -void getSNfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_sn[0]; - ip[1] = DHCP_allocated_sn[1]; - ip[2] = DHCP_allocated_sn[2]; - ip[3] = DHCP_allocated_sn[3]; -} - -void getDNSfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_dns[0]; - ip[1] = DHCP_allocated_dns[1]; - ip[2] = DHCP_allocated_dns[2]; - ip[3] = DHCP_allocated_dns[3]; -} - -uint32_t getDHCPLeasetime(void) -{ - return dhcp_lease_time; -} - -// End diff --git a/src/Network2/W5500/Wiznet/Internet/DHCP/dhcp.h b/src/Network2/W5500/Wiznet/Internet/DHCP/dhcp.h deleted file mode 100644 index 4f238b6e..00000000 --- a/src/Network2/W5500/Wiznet/Internet/DHCP/dhcp.h +++ /dev/null @@ -1,144 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.h -//! \brief DHCP APIs Header file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Move unreferenced DEFINE to dhcp.c -//! <2012/12/26> V1.1.1 -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the <ORGANIZATION> nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -#ifndef _DHCP_H_ -#define _DHCP_H_ - -/* Retry to processing DHCP */ -#define MAX_DHCP_RETRY 2 ///< Maxium retry count -#define DHCP_WAIT_TIME 10 ///< Wait Time 10s - - -/* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 ///< DHCP server port number -#define DHCP_CLIENT_PORT 68 ///< DHCP client port number - - -#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number - -#define DCHP_HOST_NAME "DuetEthernet" - -/* - * @brief return value of @ref DHCP_run() - */ -enum class DhcpRunResult : uint8_t -{ - DHCP_FAILED = 0, ///< Processing Fail - DHCP_RUNNING, ///< Processing DHCP protocol - DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) - DHCP_IP_CHANGED, ///< Change IP address by new ip from DHCP (if cbfunc == null, act as default default_ip_update) - DHCP_IP_LEASED, ///< Stand by - DHCP_STOPPED ///< Stop processing DHCP protocol -}; - -/* - * @brief DHCP client initialization (outside of the main loop) - * @param s - socket number - * @param hname - null-terminated host name string - */ -void DHCP_init(uint8_t s, const char *hname); - -/* - * @brief DHCP 1s Tick Timer handler - * @note SHOULD BE register to your system 1s Tick timer handler - */ -void DHCP_time_handler(void); - -/* - * @brief Register call back function - * @param ip_assign - callback func when IP is assigned from DHCP server first - * @param ip_update - callback func when IP is changed - * @prarm ip_conflict - callback func when the assigned IP is conflict with others. - */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - -/* - * @brief DHCP client in the main loop - * @return The value is as the follow \n - * @ref DHCP_FAILED \n - * @ref DHCP_RUNNING \n - * @ref DHCP_IP_ASSIGN \n - * @ref DHCP_IP_CHANGED \n - * @ref DHCP_IP_LEASED \n - * @ref DHCP_STOPPED \n - * - * @note This function is always called by you main task. - */ -DhcpRunResult DHCP_run(void); - -/* - * @brief Stop DHCP processing - * @note If you want to restart. call DHCP_init() and DHCP_run() - */ -void DHCP_stop(void); - -/* Get Network information assigned from DHCP server */ -/* - * @brief Get IP address - * @param ip - IP address to be returned - */ -void getIPfromDHCP(uint8_t* ip); -/* - * @brief Get Gateway address - * @param ip - Gateway address to be returned - */ -void getGWfromDHCP(uint8_t* ip); -/* - * @brief Get Subnet mask value - * @param ip - Subnet mask to be returned - */ -void getSNfromDHCP(uint8_t* ip); -/* - * @brief Get DNS address - * @param ip - DNS address to be returned - */ -void getDNSfromDHCP(uint8_t* ip); - -/* - * @brief Get the leased time by DHCP sever - * @return unit 1s - */ -uint32_t getDHCPLeasetime(void); - -#endif /* _DHCP_H_ */ diff --git a/src/Network2/W5500/Wiznet/README.md b/src/Network2/W5500/Wiznet/README.md deleted file mode 100644 index 656a263b..00000000 --- a/src/Network2/W5500/Wiznet/README.md +++ /dev/null @@ -1,54 +0,0 @@ -#ioLibrary Driver -The ioLibrary means “Internet Offload Library” for WIZnet chip. It includes drivers and application protocols. -The driver (ioLibrary) can be used for the application design of WIZnet TCP/IP chips as [W5500](http://wizwiki.net/wiki/doku.php?id=products:w5500:start), W5300, W5200 and W5100. - -##ioLibrary -This driver provides the Berkeley Socket type APIs. -- Directory Structure -<!-- ioLibrary pic --> -![ioLibrary](http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:iolibrary_bsd.jpg "ioLibrary") - -- Ethernet : SOCKET APIs like BSD & WIZCHIP([W5500](http://wizwiki.net/wiki/doku.php?id=products:w5500:start) / W5300 / W5200 / W5100) Driver -- Internet : - - DHCP client - - DNS client - - FTP client - - FTP server - - SNMP agent/trap - - SNTP client - - TFTP client - - HTTP server - - MQTT Client - - Others will be added. - -## How to add an ioLibrary in project through github site. - - Example, refer to https://www.youtube.com/watch?v=mt815RBGdsA - - [ioLibrary Doxygen doument](https://github.com/Wiznet/ioLibrary_Driver/blob/master/Ethernet/SOCKET_APIs_V2.0.chm) : Refer to **TODO** in this document - - Define what chip is used in **wizchip_conf.h** - - Define what Host I/F mode is used in **wizchip_conf.h** - -## Revision History - * ioLibrary V3.1.0 Released : 05, Dec, 2016 - * Internet application protocol add to MQTT Client (using paho MQTT 3.11) - * ioLibrary V3.0.3 Released : 03, May, 2016 - * In W5300, Fixed some compile errors in close(). Refer to M20160503 - * In close(), replace socket() with some command sequences. - * ioLibrary V3.0.2 Released : 26, April, 2016 - * Applied the erratum #1 in close() of socket.c (Refer to A20160426) - * ioLibrary V3.0.1 Released : 15, July, 2015 - * Bug fixed : In W5100, Fixed CS control problem in read/write buffer with SPI. Refer to M20150715. - * ioLibrary V3.0 Released : 01, June, 2015 - * Add to W5300 - * Typing Error in comments - * Refer to 20150601 in sources. - - * Type casting error Fixed : 09, April. 2015 - In socket.c, send() : Refer to M20150409 - - * ioLibrary V2.0 released : April. 2015 - * Added to W5100, W5200 - * Correct to some typing error - * Fixed the warning of type casting. - - * Last release : Nov. 2014 - diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.cpp b/src/Networking/ESP8266WiFi/WiFiInterface.cpp index 14ba2f4d..564637d2 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.cpp +++ b/src/Networking/ESP8266WiFi/WiFiInterface.cpp @@ -21,7 +21,7 @@ static_assert(SsidLength == SsidBufferLength, "SSID lengths in NetworkDefs.h and // Define exactly one of the following as 1, the other as zero -#if defined(DUET_WIFI) +#if defined(DUET_NG) // 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 @@ -121,12 +121,12 @@ static void EspTransferRequestIsr(CallbackParameter) static inline void EnableEspInterrupt() { - attachInterrupt(EspTransferRequestPin, EspTransferRequestIsr, RISING, nullptr); + attachInterrupt(EspDataReadyPin, EspTransferRequestIsr, RISING, nullptr); } static inline void DisableEspInterrupt() { - detachInterrupt(EspTransferRequestPin); + detachInterrupt(EspDataReadyPin); } /*-----------------------------------------------------------------------------------*/ @@ -162,7 +162,7 @@ void WiFiInterface::Init() SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway); - for (size_t i = 0; i < NumTcpSockets; ++i) + for (size_t i = 0; i < NumWiFiTcpSockets; ++i) { sockets[i]->Init(i); } @@ -389,7 +389,7 @@ void WiFiInterface::Start() pinMode(SamTfrReadyPin, OUTPUT_LOW); // Set up our data ready pin (ESP GPIO0) as an output and set it high ready to boot the ESP from flash - pinMode(EspTransferRequestPin, OUTPUT_HIGH); + pinMode(EspDataReadyPin, OUTPUT_HIGH); // GPIO2 also needs to be high to boot. It's connected to MISO on the SAM, so set the pullup resistor on that pin pinMode(APIN_SPI_MISO, INPUT_PULLUP); @@ -414,7 +414,7 @@ void WiFiInterface::Start() pinMode(SamCsPin, INPUT); // Set the data request pin to be an input - pinMode(EspTransferRequestPin, INPUT_PULLUP); + pinMode(EspDataReadyPin, INPUT_PULLUP); // The ESP takes about 300ms before it starts talking to us, so don't wait for it here, do that in Spin() spiTxUnderruns = spiRxOverruns = 0; @@ -472,7 +472,7 @@ void WiFiInterface::Spin(bool full) { // See if the ESP8266 has kept its pins at their stable values for long enough const uint32_t now = millis(); - if (digitalRead(SamCsPin) && digitalRead(EspTransferRequestPin) && !digitalRead(APIN_SPI_SCK)) + if (digitalRead(SamCsPin) && digitalRead(EspDataReadyPin) && !digitalRead(APIN_SPI_SCK)) { if (now - lastTickMillis >= WiFiStableMillis) { @@ -522,7 +522,7 @@ void WiFiInterface::Spin(bool full) case NetworkState::active: if (full) { - if (espStatusChanged && digitalRead(EspTransferRequestPin)) + if (espStatusChanged && digitalRead(EspDataReadyPin)) { if (reprap.Debug(moduleNetwork)) { @@ -573,7 +573,7 @@ void WiFiInterface::Spin(bool full) break; } ++currentSocket; - if (currentSocket == NumTcpSockets) + if (currentSocket == NumWiFiTcpSockets) { currentSocket = 0; } @@ -582,7 +582,7 @@ void WiFiInterface::Spin(bool full) // Either the current socket needs polling, or no sockets do but we must still poll one of them to get notified of any new connections sockets[currentSocket]->Poll(full); ++currentSocket; - if (currentSocket == NumTcpSockets) + if (currentSocket == NumWiFiTcpSockets) { currentSocket = 0; } @@ -607,7 +607,7 @@ void WiFiInterface::Spin(bool full) break; case NetworkState::changingMode: - if (full && espStatusChanged && digitalRead(EspTransferRequestPin)) + if (full && espStatusChanged && digitalRead(EspDataReadyPin)) { GetNewStatus(); if (currentMode != WiFiState::connecting) @@ -771,7 +771,7 @@ void WiFiInterface::Diagnostics(MessageType mtype) } } platform.Message(mtype, "Socket states:"); - for (size_t i = 0; i < NumTcpSockets; i++) + for (size_t i = 0; i < NumWiFiTcpSockets; i++) { platform.MessageF(mtype, " %d", sockets[i]->State()); } @@ -1093,6 +1093,15 @@ void WiFiInterface::UpdateHostname(const char *hostname) } } +void WiFiInterface::SetMacAddress(const uint8_t mac[]) +{ + for (size_t i = 0; i < 6; i++) + { + macAddress[i] = mac[i]; + } + // TODO actually update the mac address on the wifi module. For now we don't support this. +} + void WiFiInterface::InitSockets() { for (size_t i = 0; i < NumProtocols; ++i) @@ -1107,7 +1116,7 @@ void WiFiInterface::InitSockets() void WiFiInterface::TerminateSockets() { - for (SocketNumber skt = 0; skt < NumTcpSockets; ++skt) + for (SocketNumber skt = 0; skt < NumWiFiTcpSockets; ++skt) { sockets[skt]->Terminate(); } @@ -1127,7 +1136,7 @@ void WiFiInterface::TerminateSockets(Port port) // This is called to tell the network which sockets are active void WiFiInterface::UpdateSocketStatus(uint16_t connectedSockets, uint16_t otherEndClosedSockets) { - for (size_t i = 0; i < NumTcpSockets; ++i) + for (size_t i = 0; i < NumWiFiTcpSockets; ++i) { if (((connectedSockets | otherEndClosedSockets) & (1u << i)) != 0) { @@ -1538,7 +1547,7 @@ int32_t WiFiInterface::SendCommand(NetworkCommand cmd, SocketNumber socketNum, u // Wait for the ESP to be ready, with timeout { const uint32_t now = millis(); - while (!digitalRead(EspTransferRequestPin)) + while (!digitalRead(EspDataReadyPin)) { if (millis() - now > WiFiWaitReadyMillis) { @@ -1777,7 +1786,7 @@ void WiFiInterface::ResetWiFiForUpload(bool external) pinMode(SamTfrReadyPin, OUTPUT_LOW); // Set up our data ready pin (ESP GPIO0) as an output and set it low ready to boot the ESP from UART - pinMode(EspTransferRequestPin, OUTPUT_LOW); + pinMode(EspDataReadyPin, OUTPUT_LOW); // GPIO2 also needs to be high to boot up. It's connected to MISO on the SAM, so set the pullup resistor on that pin pinMode(APIN_SPI_MISO, INPUT_PULLUP); diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.h b/src/Networking/ESP8266WiFi/WiFiInterface.h index 9d4f54fa..35561f7c 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.h +++ b/src/Networking/ESP8266WiFi/WiFiInterface.h @@ -60,6 +60,8 @@ public: void UpdateHostname(const char *hostname) override; const uint8_t *GetIPAddress() const override { return ipAddress; } void SetIPAddress(const uint8_t ipAddress[], const uint8_t netmask[], const uint8_t gateway[]) override; + void SetMacAddress(const uint8_t mac[]) override; + const uint8_t *GetMacAddress() const override { return macAddress; } void OpenDataPort(Port port) override; void TerminateDataPort() override; @@ -123,7 +125,7 @@ private: WifiFirmwareUploader *uploader; - WiFiSocket *sockets[NumTcpSockets]; + WiFiSocket *sockets[NumWiFiTcpSockets]; size_t currentSocket; Port portNumbers[NumProtocols]; // port number used for each protocol @@ -140,6 +142,7 @@ private: uint8_t ipAddress[4]; uint8_t netmask[4]; uint8_t gateway[4]; + uint8_t macAddress[6]; char requestedSsid[SsidLength + 1]; char actualSsid[SsidLength + 1]; diff --git a/src/Networking/FirmwareUpdater.cpp b/src/Networking/FirmwareUpdater.cpp index 3ee6bf97..ad8697cc 100644 --- a/src/Networking/FirmwareUpdater.cpp +++ b/src/Networking/FirmwareUpdater.cpp @@ -19,7 +19,7 @@ namespace FirmwareUpdater { const unsigned int WifiFirmwareModule = 1; - const unsigned int WifiFilesModule = 2; + // Module 2 used to be the DWC binary file but is no longer used const unsigned int WifiExternalFirmwareModule = 3; // Check that the prerequisites are satisfied. @@ -27,7 +27,7 @@ namespace FirmwareUpdater bool CheckFirmwareUpdatePrerequisites(uint8_t moduleMap, const StringRef& reply) { #if HAS_WIFI_NETWORKING - if ((moduleMap & (1 << WifiExternalFirmwareModule)) != 0 && (moduleMap & ((1 << WifiFirmwareModule) | (1 << WifiFilesModule))) != 0) + if ((moduleMap & (1 << WifiExternalFirmwareModule)) != 0 && (moduleMap & (1 << WifiFirmwareModule)) != 0) { reply.copy("Invalid combination of firmware update modules"); return false; @@ -37,11 +37,6 @@ namespace FirmwareUpdater reply.printf("File %s not found", WIFI_FIRMWARE_FILE); return false; } - if ((moduleMap & (1 << WifiFilesModule)) != 0 && !reprap.GetPlatform().GetMassStorage()->FileExists(SYS_DIR, WIFI_WEB_FILE)) - { - reply.printf("File %s not found", WIFI_WEB_FILE); - return false; - } #endif return true; } @@ -59,32 +54,29 @@ namespace FirmwareUpdater void UpdateModule(unsigned int module) { #if HAS_WIFI_NETWORKING - switch(module) +# ifdef DUET_NG + if (reprap.GetPlatform().IsDuetWiFi()) { - case WifiExternalFirmwareModule: - reprap.GetNetwork().ResetWiFiForUpload(true); - break; - - case WifiFirmwareModule: +# endif + switch(module) { - WifiFirmwareUploader * const uploader = reprap.GetNetwork().GetWifiUploader(); - if (uploader != nullptr) - { - uploader->SendUpdateFile(WIFI_FIRMWARE_FILE, SYS_DIR, WifiFirmwareUploader::FirmwareAddress); - } - } - break; + case WifiExternalFirmwareModule: + reprap.GetNetwork().ResetWiFiForUpload(true); + break; - case WifiFilesModule: - { - WifiFirmwareUploader * const uploader = reprap.GetNetwork().GetWifiUploader(); - if (uploader != nullptr) + case WifiFirmwareModule: { - uploader->SendUpdateFile(WIFI_WEB_FILE, SYS_DIR, WifiFirmwareUploader::WebFilesAddress); + WifiFirmwareUploader * const uploader = reprap.GetNetwork().GetWifiUploader(); + if (uploader != nullptr) + { + uploader->SendUpdateFile(WIFI_FIRMWARE_FILE, SYS_DIR, WifiFirmwareUploader::FirmwareAddress); + } } + break; } - break; +# ifdef DUET_NG } +# endif #endif } } diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp index 2e9034b3..9d129ecd 100644 --- a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp +++ b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp @@ -145,6 +145,8 @@ void LwipEthernetInterface::Init() { listeningPcbs[i] = nullptr; } + + memcpy(macAddress, platform.GetDefaultMacAddress(), sizeof(macAddress)); } GCodeResult LwipEthernetInterface::EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) @@ -344,7 +346,7 @@ void LwipEthernetInterface::Start() const char *hostname = reprap.GetNetwork().GetHostname(); // Allow the MAC address to be set only before LwIP is started... - ethernet_configure_interface(platform.MACAddress(), hostname); + ethernet_configure_interface(platform.GetDefaultMacAddress(), hostname); init_ethernet(DefaultIpAddress, DefaultNetMask, DefaultGateway); // Initialise mDNS subsystem @@ -542,16 +544,6 @@ int LwipEthernetInterface::EnableState() const return (state == NetworkState::disabled) ? 0 : 1; } -bool LwipEthernetInterface::Lock() -{ - return LockLWIP(); -} - -void LwipEthernetInterface::Unlock() -{ - UnlockLWIP(); -} - bool LwipEthernetInterface::InNetworkStack() const { return lwipLocked; @@ -622,6 +614,11 @@ void LwipEthernetInterface::UpdateHostname(const char *hostname) } } +void LwipEthernetInterface::SetMacAddress(const uint8_t mac[]) +{ + memcpy(macAddress, mac, sizeof(macAddress)); +} + void LwipEthernetInterface::OpenDataPort(Port port) { if (listeningPcbs[NumProtocols] != nullptr) diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.h b/src/Networking/LwipEthernet/LwipEthernetInterface.h index 4ffbb69b..c816e573 100644 --- a/src/Networking/LwipEthernet/LwipEthernetInterface.h +++ b/src/Networking/LwipEthernet/LwipEthernetInterface.h @@ -44,14 +44,6 @@ public: GCodeResult DisableProtocol(NetworkProtocol protocol, const StringRef& reply) override; GCodeResult ReportProtocols(const StringRef& reply) const override; - // LwIP interfaces - void ResetCallback(); - bool Lock(); - void Unlock(); - - bool ConnectionEstablished(tcp_pcb *pcb); - - // Global settings GCodeResult GetNetworkState(const StringRef& reply) override; int EnableState() const override; bool InNetworkStack() const override; @@ -60,6 +52,11 @@ public: void UpdateHostname(const char *hostname) override; const uint8_t *GetIPAddress() const override; void SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]) override; + void SetMacAddress(const uint8_t mac[]) override; + const uint8_t *GetMacAddress() const override { return macAddress; } + + // LwIP interfaces + bool ConnectionEstablished(tcp_pcb *pcb); void OpenDataPort(Port port) override; void TerminateDataPort() override; @@ -104,6 +101,8 @@ private: bool activated; bool initialised; bool usingDhcp; + + uint8_t macAddress[6]; }; #endif diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp index 8a1637d5..3dd42c52 100644 --- a/src/Networking/Network.cpp +++ b/src/Networking/Network.cpp @@ -35,18 +35,24 @@ Network::Network(Platform& p) : platform(p), responders(nullptr), nextResponderToPoll(nullptr) { - // Create the network modules - #if defined(SAME70_TEST_BOARD) interfaces[0] = new LwipEthernetInterface(p); interfaces[1] = new WiFiInterface(p); -#elif defined(DUET_WIFI) - interfaces[0] = new WiFiInterface(p); -#elif defined(DUET_ETHERNET) || defined(DUET_M) +#elif defined(DUET_NG) + interfaces[0] = nullptr; // we set this up in Init() +#elif defined(DUET_M) interfaces[0] = new W5500Interface(p); #else # error Unknown board #endif +} + +// Note that Platform::Init() must be called before this to that Platform::IsDuetWiFi() returns the correct value +void Network::Init() +{ +#if defined(DUET_NG) + interfaces[0] = (platform.IsDuetWiFi()) ? static_cast<NetworkInterface*>(new WiFiInterface(platform)) : static_cast<NetworkInterface*>(new W5500Interface(platform)); +#endif // Create the responders for (size_t i = 0; i < NumTelnetResponders; ++i) @@ -61,11 +67,7 @@ Network::Network(Platform& p) : platform(p), responders(nullptr), nextResponderT { responders = new HttpResponder(responders); } -} -void Network::Init() -{ - longWait = millis(); strcpy(hostname, DEFAULT_HOSTNAME); NetworkBuffer::AllocateBuffers(NetworkBufferCount); @@ -74,6 +76,8 @@ void Network::Init() { iface->Init(); } + + longWait = millis(); } GCodeResult Network::EnableProtocol(unsigned int interface, NetworkProtocol protocol, int port, int secure, const StringRef& reply) @@ -161,7 +165,7 @@ const char* Network::GetWiFiServerVersion() const } #endif - return "(not defined)"; + return "no WiFi interface"; } WifiFirmwareUploader *Network::GetWifiUploader() const @@ -374,6 +378,24 @@ void Network::SetHostname(const char *name) } } +// Net the MAC address. Pass -1 as the interface number to set the default MAC address for interfaces that don't have one. +void Network::SetMacAddress(unsigned int interface, const uint8_t mac[]) +{ + if (interface < NumNetworkInterfaces) + { + interfaces[interface]->SetMacAddress(mac); + } +} + +const uint8_t *Network::GetMacAddress(unsigned int interface) const +{ + if (interface >= NumNetworkInterfaces) + { + interface = 0; + } + return interfaces[interface]->GetMacAddress(); +} + // Find a responder to process a new connection bool Network::FindResponder(Socket *skt, NetworkProtocol protocol) { diff --git a/src/Networking/Network.h b/src/Networking/Network.h index c90be5bd..6cd2d268 100644 --- a/src/Networking/Network.h +++ b/src/Networking/Network.h @@ -66,9 +66,10 @@ public: int EnableState(unsigned int interface) const; void SetEthernetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]); - const char *GetHostname() const { return hostname; } void SetHostname(const char *name); + void SetMacAddress(unsigned int interface, const uint8_t mac[]); + const uint8_t *GetMacAddress(unsigned int interface) const; bool FindResponder(Socket *skt, NetworkProtocol protocol); diff --git a/src/Networking/NetworkBuffer.h b/src/Networking/NetworkBuffer.h index a15306be..feb4162c 100644 --- a/src/Networking/NetworkBuffer.h +++ b/src/Networking/NetworkBuffer.h @@ -86,12 +86,8 @@ private: NetworkBuffer *next; size_t dataLength; size_t readPointer; -#ifdef DUET_WIFI - // When doing unaligned transfers on the WiFi interface, up to 3 extra bytes may be returned + // When doing unaligned transfers on the WiFi interface, up to 3 extra bytes may be returned, hence the +1 in the following uint32_t data32[bufferSize/sizeof(uint32_t) + 1]; // 32-bit aligned buffer so we can do direct DMA -#else - uint32_t data32[bufferSize/sizeof(uint32_t)]; // 32-bit aligned buffer so we can do direct DMA -#endif static NetworkBuffer *freelist; }; diff --git a/src/Networking/NetworkInterface.h b/src/Networking/NetworkInterface.h index 451b2edd..a292d34b 100644 --- a/src/Networking/NetworkInterface.h +++ b/src/Networking/NetworkInterface.h @@ -35,6 +35,8 @@ public: virtual const uint8_t *GetIPAddress() const = 0; virtual void SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]) = 0; + virtual void SetMacAddress(const uint8_t mac[]) = 0; + virtual const uint8_t *GetMacAddress() const = 0; virtual void UpdateHostname(const char *hostname) = 0; diff --git a/src/Networking/W5500Ethernet/W5500Interface.cpp b/src/Networking/W5500Ethernet/W5500Interface.cpp index 511cc824..27cf6185 100644 --- a/src/Networking/W5500Ethernet/W5500Interface.cpp +++ b/src/Networking/W5500Ethernet/W5500Interface.cpp @@ -40,6 +40,7 @@ void W5500Interface::Init() lastTickMillis = millis(); SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway); + memcpy(macAddress, platform.GetDefaultMacAddress(), sizeof(macAddress)); } GCodeResult W5500Interface::EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) @@ -209,6 +210,15 @@ GCodeResult W5500Interface::GetNetworkState(const StringRef& reply) return GCodeResult::ok; } +// Update the MAC address +void W5500Interface::SetMacAddress(const uint8_t mac[]) +{ + for (size_t i = 0; i < 6; i++) + { + macAddress[i] = mac[i]; + } +} + // Start up the network void W5500Interface::Start() { @@ -226,7 +236,7 @@ void W5500Interface::Start() wizchip_init(bufSizes, bufSizes); - setSHAR(platform.MACAddress()); + setSHAR(macAddress); setSIPR(ipAddress); setGAR(gateway); setSUBR(netmask); @@ -346,7 +356,7 @@ void W5500Interface::Spin(bool full) // Move on to the next TCP socket for next time ++nextSocketToPoll; - if (nextSocketToPoll == NumTcpSockets) + if (nextSocketToPoll == NumW5500TcpSockets) { nextSocketToPoll = 0; } @@ -439,7 +449,7 @@ void W5500Interface::DataPortClosing() void W5500Interface::TerminateSockets() { - for (SocketNumber skt = 0; skt < NumTcpSockets; ++skt) + for (SocketNumber skt = 0; skt < NumW5500TcpSockets; ++skt) { sockets[skt]->Terminate(); } diff --git a/src/Networking/W5500Ethernet/W5500Interface.h b/src/Networking/W5500Ethernet/W5500Interface.h index cde7014d..69fa1433 100644 --- a/src/Networking/W5500Ethernet/W5500Interface.h +++ b/src/Networking/W5500Ethernet/W5500Interface.h @@ -24,7 +24,7 @@ const size_t NumHttpSockets = 4; // sockets 0-3 are for HTTP const SocketNumber FtpSocketNumber = 4; const SocketNumber FtpDataSocketNumber = 5; // TODO can we allocate this dynamically when required, to allow more http sockets most of the time? const SocketNumber TelnetSocketNumber = 6; -const size_t NumTcpSockets = 7; +const size_t NumW5500TcpSockets = 7; const SocketNumber DhcpSocketNumber = 7; // TODO can we allocate this dynamically when required, to allow more http sockets most of the time? class Platform; @@ -51,11 +51,13 @@ public: GCodeResult GetNetworkState(const StringRef& reply) override; int EnableState() const override; bool InNetworkStack() const override { return false; } - bool IsWiFiInterface() const override { return true; } + bool IsWiFiInterface() const override { return false; } void UpdateHostname(const char *name) override { } - const uint8_t *GetIPAddress() const override { return ipAddress; } + void SetMacAddress(const uint8_t mac[]) override; + const uint8_t *GetMacAddress() const override { return macAddress; } + void OpenDataPort(Port port) override; void TerminateDataPort() override; void DataPortClosing() override; @@ -84,11 +86,10 @@ private: pre(protocol < NumProtocols); void SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]); - Platform& platform; uint32_t lastTickMillis; - W5500Socket *sockets[NumTcpSockets]; + W5500Socket *sockets[NumW5500TcpSockets]; size_t nextSocketToPoll; // next TCP socket number to poll for read/write operations Port portNumbers[NumProtocols]; // port number used for each protocol @@ -101,6 +102,7 @@ private: uint8_t ipAddress[4]; uint8_t netmask[4]; uint8_t gateway[4]; + uint8_t macAddress[6]; }; #endif diff --git a/src/Platform.cpp b/src/Platform.cpp index e116c335..28c014f2 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -352,6 +352,7 @@ Platform::Platform() : //******************************************************************************************************************* +// Initialise the Platform. Note: this is the first module to be initialised, so don't call other modules from here! void Platform::Init() { // Deal with power first @@ -385,14 +386,15 @@ void Platform::Init() #endif compatibility = marlin; // default to Marlin because the common host programs expect the "OK" response to commands + + // File management + massStorage->Init(); + ARRAY_INIT(ipAddress, DefaultIpAddress); ARRAY_INIT(netMask, DefaultNetMask); ARRAY_INIT(gateWay, DefaultGateway); -#if defined(DUET_NG) && defined(DUET_WIFI) - // The WiFi module has a unique MAC address, so we don't need a default - memset(macAddress, 0xFF, sizeof(macAddress)); -#elif (defined(DUET_NG) && defined(DUET_ETHERNET)) || (defined(__SAME70Q21__)) +#if defined(DUET_NG) || defined(SAME70_TEST_BOARD) // On the Duet Ethernet and SAM E70, use the unique chip ID as most of the MAC address. // The unique ID is 128 bits long whereas the whole MAC address is only 48 bits, // so we can't guarantee that each Duet will get a unique MAC address this way. @@ -401,33 +403,27 @@ void Platform::Init() memset(idBuf, 0, sizeof(idBuf)); DisableCache(); cpu_irq_disable(); - uint32_t rc = flash_read_unique_id(idBuf, 4); + const uint32_t rc = flash_read_unique_id(idBuf, 4); cpu_irq_enable(); EnableCache(); if (rc == 0) { - memset(macAddress, 0, sizeof(macAddress)); - macAddress[0] = 0xBE; // use a fixed first byte with the locally-administered bit set + memset(defaultMacAddress, 0, sizeof(defaultMacAddress)); + defaultMacAddress[0] = 0xBE; // use a fixed first byte with the locally-administered bit set const uint8_t * const idBytes = reinterpret_cast<const uint8_t *>(idBuf); for (size_t i = 0; i < 15; ++i) { - macAddress[(i % 5) + 1] ^= idBytes[i]; + defaultMacAddress[(i % 5) + 1] ^= idBytes[i]; } } else { - ARRAY_INIT(macAddress, DefaultMacAddress); + ARRAY_INIT(defaultMacAddress, DefaultMacAddress); } } -#else - // Set the default MAC address. The user must change it manually if using more than one Duet 06 or 085 on a network. - ARRAY_INIT(macAddress, DefaultMacAddress); -#endif - - // File management - massStorage->Init(); +#elif defined(DUET_06_085) + ARRAY_INIT(defaultMacAddress, DefaultMacAddress); -#if defined(DUET_06_085) // Motor current setting on Duet 0.6 and 0.8.5 InitI2c(); mcpExpansion.setMCP4461Address(0x2E); // not required for mcpDuet, as this uses the default address @@ -436,19 +432,20 @@ void Platform::Init() maxStepperDigipotVoltage = MAX_STEPPER_DIGIPOT_VOLTAGE; stepperDacVoltageRange = STEPPER_DAC_VOLTAGE_RANGE; stepperDacVoltageOffset = STEPPER_DAC_VOLTAGE_OFFSET; -#endif - -#if defined(__ALLIGATOR__) +#elif defined(__ALLIGATOR__) pinMode(EthernetPhyResetPin, INPUT); // Init Ethernet Phy Reset Pin + // Alligator Init DAC for motor current vref ARRAY_INIT(spiDacCS, SPI_DAC_CS); dacAlligator.Init(spiDacCS[0]); dacPiggy.Init(spiDacCS[1]); // Get macaddress from EUI48 eeprom eui48MacAddress.Init(Eui48csPin); - if(! eui48MacAddress.getEUI48(macAddress)) { - ARRAY_INIT(macAddress, DefaultMacAddress); + if (!eui48MacAddress.getEUI48(defaultMacAddress)) + { + ARRAY_INIT(defaultMacAddress, DefaultMacAddress); } + Microstepping::Init(); // Init Motor FAULT detect Pin pinMode(ExpansionVoltageLevelPin, ExpansionVoltageLevel==3 ? OUTPUT_LOW : OUTPUT_HIGH); // Init Expansion Voltage Level Pin pinMode(MotorFaultDetectPin,INPUT); // Init Motor FAULT detect Pin @@ -3423,14 +3420,6 @@ void Platform::InitFans() } } -void Platform::SetMACAddress(uint8_t mac[]) -{ - for (size_t i = 0; i < 6; i++) - { - macAddress[i] = mac[i]; - } -} - void Platform::SetEndStopConfiguration(size_t axis, EndStopPosition esPos, EndStopInputType inputType) { endStopPos[axis] = esPos; @@ -3920,9 +3909,13 @@ void Platform::SetBoardType(BoardType bt) { if (bt == BoardType::Auto) { -#if defined(__SAME70Q21__) - board = BoardType::SAME70_TEST; +#if defined(SAME70_TEST_BOARD) + board = BoardType::SamE70TestBoard; #elif defined(DUET_NG) + // Get ready to test whether the Ethernet module is present, so that we avoid additional delays + pinMode(EspResetPin, OUTPUT_LOW); // reset the WiFi module or the W5500. We assume that this forces the ESP8266 UART output pin to high impedance. + pinMode(W5500ModuleSensePin, INPUT_PULLUP); // set our UART receive pin to be an input pin and enable the pullup + // Set up the VSSA sense pin. Older Duet WiFis don't have it connected, so we enable the pulldown resistor to keep it inactive. pinMode(VssaSensePin, INPUT_PULLUP); delayMicroseconds(10); @@ -3936,11 +3929,15 @@ void Platform::SetBoardType(BoardType bt) pinMode(VssaSensePin, INPUT); } -# if defined(DUET_WIFI) - board = (vssaSenseWorking) ? BoardType::DuetWiFi_102 : BoardType::DuetWiFi_10; -# elif defined(DUET_ETHERNET) - board = (vssaSenseWorking) ? BoardType::DuetEthernet_102 : BoardType::DuetEthernet_10; -# endif + // Test whether the Ethernet module is present + if (digitalRead(W5500ModuleSensePin)) // the Ethernet module has this pin grounded + { + board = (vssaSenseWorking) ? BoardType::DuetWiFi_102 : BoardType::DuetWiFi_10; + } + else + { + board = (vssaSenseWorking) ? BoardType::DuetEthernet_102 : BoardType::DuetEthernet_10; + } #elif defined(DUET_M) board = BoardType::DuetM_10; #elif defined(DUET_06_085) @@ -3949,6 +3946,7 @@ void Platform::SetBoardType(BoardType bt) // So we enable the pullup (value 100K-150K) on pin 67 and read it, expecting a LOW on a 0.8.5 board and a HIGH on a 0.6 board. // This may fail if anyone connects a load to the DAC0 pin on a Duet 0.6, hence we implement board selection in M115 as well. pinMode(Dac0DigitalPin, INPUT_PULLUP); + delayMicroseconds(10); board = (digitalRead(Dac0DigitalPin)) ? BoardType::Duet_06 : BoardType::Duet_085; pinMode(Dac0DigitalPin, INPUT); // turn pullup off #elif defined(__RADDS__) @@ -3976,12 +3974,11 @@ const char* Platform::GetElectronicsString() const { switch (board) { -#if defined(__SAME70Q21__) - case BoardType::SAME70_TEST: return "SAM E70 prototype 1"; -#elif defined(DUET_NG) && defined(DUET_WIFI) +#if defined(SAME70_TEST_BOARD) + case BoardType::SamE70TestBoard: return "SAM E70 prototype 1"; +#elif defined(DUET_NG) case BoardType::DuetWiFi_10: return "Duet WiFi 1.0 or 1.01"; case BoardType::DuetWiFi_102: return "Duet WiFi 1.02 or later"; -#elif defined(DUET_NG) && defined(DUET_ETHERNET) case BoardType::DuetEthernet_10: return "Duet Ethernet 1.0 or 1.01"; case BoardType::DuetEthernet_102: return "Duet Ethernet 1.02 or later"; #elif defined(DUET_M) @@ -4006,12 +4003,11 @@ const char* Platform::GetBoardString() const { switch (board) { -#if defined(__SAME70Q21__) - case BoardType::SAME70_TEST: return "same70prototype1"; -#elif defined(DUET_NG) && defined(DUET_WIFI) +#if defined(SAME70_TEST_BOARD) + case BoardType::SamE70TestBoard: return "same70prototype1"; +#elif defined(DUET_NG) case BoardType::DuetWiFi_10: return "duetwifi10"; case BoardType::DuetWiFi_102: return "duetwifi102"; -#elif defined(DUET_NG) && defined(DUET_ETHERNET) case BoardType::DuetEthernet_10: return "duetethernet10"; case BoardType::DuetEthernet_102: return "duetethernet102"; #elif defined(DUET_M) @@ -4031,6 +4027,14 @@ const char* Platform::GetBoardString() const } } +#ifdef DUET_NG +// Return true if this is a Duet WiFi, false if it is a Duet Ethernet +bool Platform::IsDuetWiFi() const +{ + return board == BoardType::DuetWiFi_10 || board == BoardType::DuetWiFi_102; +} +#endif + // User I/O and servo support bool Platform::GetFirmwarePin(LogicalPin logicalPin, PinAccess access, Pin& firmwarePin, bool& invert) { diff --git a/src/Platform.h b/src/Platform.h index 2ff3bb6e..0bb9c64e 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -111,14 +111,13 @@ constexpr uint32_t maxPidSpinDelay = 5000; // Maximum elapsed time in millisec enum class BoardType : uint8_t { Auto = 0, -#if defined(__SAME70Q21__) - SAME70_TEST = 1 -#elif defined(DUET_NG) && defined(DUET_WIFI) +#if defined(SAME70_TEST_BOARD) + SamE70TestBoard = 1 +#elif defined(DUET_NG) DuetWiFi_10 = 1, - DuetWiFi_102 = 2 -#elif defined(DUET_NG) && defined(DUET_ETHERNET) - DuetEthernet_10 = 1, - DuetEthernet_102 = 2 + DuetWiFi_102 = 2, + DuetEthernet_10 = 3, + DuetEthernet_102 = 4 #elif defined(DUET_M) DuetM_10 = 1, #elif defined(DUET_06_085) @@ -330,6 +329,12 @@ public: const char* GetElectronicsString() const; const char* GetBoardString() const; +#ifdef DUET_NG + bool IsDuetWiFi() const; +#endif + + const uint8_t *GetDefaultMacAddress() const { return defaultMacAddress; } + // Timing static uint32_t GetInterruptClocks() __attribute__ ((hot)); // Get the interrupt clock count static uint32_t GetInterruptClocksInterruptsDisabled() __attribute__ ((hot)); // Get the interrupt clock count, when we know already that interrupts are disabled @@ -358,8 +363,6 @@ public: const uint8_t* NetMask() const; void SetGateWay(uint8_t gw[]); const uint8_t* GateWay() const; - void SetMACAddress(uint8_t mac[]); - const uint8_t* MACAddress() const; void SetBaudRate(size_t chan, uint32_t br); uint32_t GetBaudRate(size_t chan) const; void SetCommsProperties(size_t chan, uint32_t cp); @@ -694,7 +697,7 @@ private: byte ipAddress[4]; byte netMask[4]; byte gateWay[4]; - uint8_t macAddress[6]; + uint8_t defaultMacAddress[6]; Compatibility compatibility; BoardType board; @@ -1117,11 +1120,6 @@ inline const uint8_t* Platform::GateWay() const return gateWay; } -inline const uint8_t* Platform::MACAddress() const -{ - return macAddress; -} - inline float Platform::GetPressureAdvance(size_t extruder) const { return (extruder < MaxExtruders) ? pressureAdvance[extruder] : 0.0; diff --git a/src/RADDS/Network.h b/src/RADDS/Network.h index b8aae90c..88c9771a 100644 --- a/src/RADDS/Network.h +++ b/src/RADDS/Network.h @@ -5,10 +5,10 @@ #include "MessageType.h" #include "GCodes/GCodeResult.h" -const uint8_t DefaultMacAddress[6] = { 0, 0, 0, 0, 0, 0 }; const uint8_t DefaultIpAddress[4] = { 0, 0, 0, 0 }; const uint8_t DefaultNetMask[4] = { 0, 0, 0, 0 }; const uint8_t DefaultGateway[4] = { 0, 0, 0, 0 }; +const uint8_t macAddress[6] = { 0, 0, 0, 0, 0, 0 }; const size_t SsidBufferLength = 32; // maximum characters in an SSID @@ -32,6 +32,8 @@ public: GCodeResult GetNetworkState(unsigned int interface, const StringRef& reply); void SetEthernetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[], const uint8_t p_gateway[]) { } + void SetMacAddress(unsigned int interface, const uint8_t mac[]) { } + const uint8_t *GetMacAddress(unsigned int interface) const { return macAddress; } void SetHostname(const char *name) const { } bool IsWiFiInterface(unsigned int interface) const { return false; } diff --git a/src/RepRap.cpp b/src/RepRap.cpp index 8340fe17..e3773711 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -94,7 +94,6 @@ RepRap::RepRap() : toolList(nullptr), currentTool(nullptr), lastWarningMillis(0) printMonitor = new PrintMonitor(*platform, *gCodes); SetPassword(DEFAULT_PASSWORD); - SetName(DEFAULT_MACHINE_NAME); message[0] = 0; } @@ -102,8 +101,9 @@ void RepRap::Init() { // All of the following init functions must execute reasonably quickly before the watchdog times us out platform->Init(); - gCodes->Init(); network->Init(); + SetName(DEFAULT_MACHINE_NAME); // network must be initialised before calling this because it calls SetHostName + gCodes->Init(); move->Init(); heat->Init(); #if SUPPORT_ROLAND @@ -119,7 +119,7 @@ void RepRap::Init() #if SUPPORT_12864_LCD display->Init(); #endif - active = true; // must do this before we start the network, else the watchdog may time out + active = true; // must do this before we start the network, else the watchdog may time out platform->MessageF(UsbMessage, "%s Version %s dated %s\n", FIRMWARE_NAME, VERSION, DATE); @@ -1234,9 +1234,19 @@ OutputBuffer *RepRap::GetConfigResponse() #endif response->catf("\",\"firmwareName\":\"%s\"", FIRMWARE_NAME); response->catf(",\"firmwareVersion\":\"%s\"", VERSION); + #if HAS_WIFI_NETWORKING - response->catf(",\"dwsVersion\":\"%s\"", network->GetWiFiServerVersion()); + // If we have WiFi networking, send the WiFi module firmware version +# ifdef DUET_NG + if (platform->IsDuetWiFi()) + { +# endif + response->catf(",\"dwsVersion\":\"%s\"", network->GetWiFiServerVersion()); +# ifdef DUET_NG + } +# endif #endif + response->catf(",\"firmwareDate\":\"%s\"", DATE); // Motor idle parameters diff --git a/src/SAME70_TEST/Pins_SAME70_TEST.h b/src/SAME70_TEST/Pins_SAME70_TEST.h index 6c8f2b6b..ae46f694 100644 --- a/src/SAME70_TEST/Pins_SAME70_TEST.h +++ b/src/SAME70_TEST/Pins_SAME70_TEST.h @@ -1,9 +1,9 @@ #ifndef PINS_SAME70_H__ #define PINS_SAME70_H__ -# define FIRMWARE_NAME "RepRapFirmware for SAME70" -# define DEFAULT_BOARD_TYPE BoardType::SAME70_TEST -const size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manual upload to WiFi module +# define FIRMWARE_NAME "RepRapFirmware for SAME70" +# define DEFAULT_BOARD_TYPE BoardType::SamE70TestBoard +const size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manual upload to WiFi module (module 2 not used) # define IAP_FIRMWARE_FILE "SAME70Firmware.bin" # define WIFI_FIRMWARE_FILE "DuetWiFiServer.bin" # define WIFI_WEB_FILE "DuetWebControl.bin" @@ -160,7 +160,7 @@ constexpr uint32_t IAP_FLASH_END = 0x0047FFFF; // we allow a full 64K on the SA // Duet pin numbers to control the WiFi interface constexpr Pin EspResetPin = 19; // Low on this in holds the WiFi module in reset (ESP_RESET) constexpr Pin EspEnablePin = 48; // High to enable the WiFi module, low to power it down (ESP_CH_PD) -constexpr Pin EspTransferRequestPin = 12; // Input from the WiFi module indicating that it wants to transfer data (ESP GPIO0) +constexpr Pin EspDataReadyPin = 12; // Input from the WiFi module indicating that it wants to transfer data (ESP GPIO0) constexpr Pin SamTfrReadyPin = 36; // Output from the SAM to the WiFi module indicating we can accept a data transfer (ESP GPIO4 via 7474) constexpr Pin SamCsPin = 20; // SPI NPCS pin, input from WiFi module diff --git a/src/Version.h b/src/Version.h index 8a7eaed2..4554357a 100644 --- a/src/Version.h +++ b/src/Version.h @@ -13,7 +13,7 @@ #endif #ifndef DATE -# define DATE "2018-02-10 build 1" +# define DATE "2018-02-12 build 1" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman" |