diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a46b6ce --- /dev/null +++ b/.clang-format @@ -0,0 +1,18 @@ +--- +AlignAfterOpenBracket: AlwaysBreak +AllowShortBlocksOnASingleLine: 'false' +BinPackArguments: 'false' +BinPackParameters: 'false' +BreakBeforeBraces: Allman +BreakConstructorInitializers: AfterColon +ColumnLimit: '100' +ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' +IndentWidth: '4' +MaxEmptyLinesToKeep: '1' +NamespaceIndentation: All +PointerAlignment: Left +SortIncludes: 'true' +TabWidth: '4' +UseTab: Always + +... diff --git a/Makefile b/Makefile index 88e1e97..9b15aa4 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ OBJS = armc-start.o armc-cstartup.o armc-cstubs.o armc-cppstubs.o \ Drive.o Pi1541.o DiskImage.o iec_bus.o iec_commands.o m6502.o m6522.o \ gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o SSD1306.o ScreenLCD.o \ Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o m8520.o wd177x.o Pi1581.o SpinLock.o \ - net-tftp.o net-arp.o net-ethernet.o net-icmp.o net-ipv4.o net-udp.o net-dhcp.o net-utils.o + net.o net-tftp.o net-arp.o net-ethernet.o net-icmp.o net-ipv4.o net-udp.o net-dhcp.o net-utils.o SRCDIR = src OBJS := $(addprefix $(SRCDIR)/, $(OBJS)) diff --git a/src/main.cpp b/src/main.cpp index 185baab..8ed7058 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -367,40 +367,6 @@ void InitialiseLCD() // printf("\E[1ALED %s%d\E[0m Motor %d Track %0d.%d ATN %d DAT %d CLK %d %s\r\n", LED ? termainalTextRed : termainalTextNormal, LED, Motor, Track >> 1, Track & 1 ? 5 : 0, ATN, DATA, CLOCK, roms.ROMNames[romIndex]); //} -void updateNetwork() -{ - unsigned int frameSize = 0; - uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE]; - if (!USPiEthernetAvailable() || !USPiReceiveFrame(ipBuffer, &frameSize)) - { - return; - } - - Net::Ethernet::Header ethernetHeader; - auto headerSize = Net::Ethernet::Header::Deserialize( - ethernetHeader, ipBuffer, frameSize); - assert(headerSize != 0); - - static bool arpAnnouncementSent = false; - if (!arpAnnouncementSent) - { - Net::Arp::SendAnnouncement( - Net::Utils::GetMacAddress(), Net::Utils::Ipv4Address); - arpAnnouncementSent = true; - } - - switch (ethernetHeader.type) - { - case Net::Ethernet::EtherType::Arp: - Net::Arp::HandlePacket(ethernetHeader, ipBuffer + headerSize); - break; - case Net::Ethernet::EtherType::Ipv4: - Net::Ipv4::HandlePacket( - ethernetHeader, ipBuffer + headerSize, frameSize - headerSize); - break; - } -} - // This runs on core0 and frees up core1 to just run the emulator. // Care must be taken not to crowd out the shared cache with core1 as this could slow down core1 so that it no longer can perform its duties in the 1us timings it requires. void UpdateScreen() @@ -665,7 +631,7 @@ void UpdateScreen() //if (options.GetSupportUARTInput()) // UpdateUartControls(refreshUartStatusDisplay, oldLED, oldMotor, oldATN, oldDATA, oldCLOCK, oldTrack, romIndex); - updateNetwork(); + Net::Update(); // Go back to sleep. The USB irq will wake us up again. __asm ("WFE"); @@ -1984,13 +1950,9 @@ extern "C" inputMappings = new InputMappings(); //USPiMouseRegisterStatusHandler(MouseHandler); - while (!USPiEthernetAvailable()) { - snprintf(tempBuffer, tempBufferSize, "Waiting for ethernet..."); - screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); - MsDelay(500); - } CheckOptions(); + Net::Initialize(options); IEC_Bus::SetSplitIECLines(options.SplitIECLines()); IEC_Bus::SetInvertIECInputs(options.InvertIECInputs()); diff --git a/src/net-dhcp.cpp b/src/net-dhcp.cpp index 19ddbd4..0c18a05 100644 --- a/src/net-dhcp.cpp +++ b/src/net-dhcp.cpp @@ -166,24 +166,33 @@ namespace Net::Dhcp USPiSendFrame(buffer, size); } - void discoverTimerHandler(unsigned int hTimer, void* nParam, void* nContext) + void discoverTimerHandler(unsigned int, void* callbackVoid, void*) { if (transactionId == 0 || offeredIpAddresses.empty()) { + // TODO retry every minute or so? return; } // Select the first IP address - const auto clientIpAddress = offeredIpAddresses[0]; + Utils::Ipv4Address = offeredIpAddresses[0]; // Send DHCP Requests to every server with that IP address. for (size_t i = 0; i < serverIpAddresses.size(); i++) { - sendRequest(clientIpAddress, serverMacAddresses[i], serverIpAddresses[i]); + sendRequest( + Utils::Ipv4Address, serverMacAddresses[i], serverIpAddresses[i]); + } + + // Run the callback indicating an IP has been obtained + if (callbackVoid != nullptr) + { + const auto& callback = *static_cast*>(callbackVoid); + callback(); } } - void SendDiscover() + void sendDiscover() { transactionId = std::rand(); offeredIpAddresses.clear(); @@ -216,9 +225,15 @@ namespace Net::Dhcp assert(size <= sizeof(buffer)); USPiSendFrame(buffer, size); + } - // Wait a second for responses - StartKernelTimer(1 * HZ, discoverTimerHandler, nullptr, nullptr); + void ObtainIp(std::function& callback) + { + sendDiscover(); + + // Wait three seconds for responses + const auto callbackVoid = static_cast(&callback); + StartKernelTimer(3 * HZ, discoverTimerHandler, callbackVoid, nullptr); } static void handleOfferPacket( diff --git a/src/net-dhcp.h b/src/net-dhcp.h index 7ca8190..1bc4c01 100644 --- a/src/net-dhcp.h +++ b/src/net-dhcp.h @@ -1,4 +1,5 @@ #pragma once +#include #include "net.h" #include "net-ethernet.h" @@ -88,7 +89,7 @@ namespace Net::Dhcp Header& out, const uint8_t* buffer, const size_t size); }; - void SendDiscover(); + void ObtainIp(std::function& callback); void HandlePacket( const Ethernet::Header& ethernetHeader, const uint8_t* buffer, diff --git a/src/net.cpp b/src/net.cpp new file mode 100644 index 0000000..141c5e8 --- /dev/null +++ b/src/net.cpp @@ -0,0 +1,94 @@ +#include "net.h" + +#include "debug.h" +#include "options.h" +#include "types.h" +#include +#include + +namespace Net +{ + static void postInitialize(unsigned int, void* parameter, void*); + static void ipObtained(); + + void Initialize(Options& options) + { + // Wait for ethernet to become available. + while (!USPiEthernetAvailable()) + { + MsDelay(500); + } + + // Wait 3 seconds, then run postInitialize + const auto optionsVoid = static_cast(&options); + StartKernelTimer(3 * HZ, postInitialize, optionsVoid, nullptr); + } + + void Update() + { + unsigned int bufferSize = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + if (!USPiEthernetAvailable() || !USPiReceiveFrame(buffer, &bufferSize)) + { + return; + } + + Ethernet::Header ethernetHeader; + auto headerSize = Ethernet::Header::Deserialize(ethernetHeader, buffer, bufferSize); + if (headerSize == 0 || headerSize != Ethernet::Header::SerializedLength()) + { + DEBUG_LOG( + "Dropped ethernet packet (invalid buffer size %lu, expected at least %lu)\r\n", + headerSize, + Ethernet::Header::SerializedLength()); + return; + } + + switch (ethernetHeader.type) + { + case Ethernet::EtherType::Arp: + Arp::HandlePacket(ethernetHeader, buffer + headerSize, bufferSize - headerSize); + break; + case Ethernet::EtherType::Ipv4: + Ipv4::HandlePacket(ethernetHeader, buffer + headerSize, bufferSize - headerSize); + break; + } + } + + static void postInitialize(unsigned int, void* parameter, void*) + { + DEBUG_LOG("Running network post-init\r\n"); + const auto options = static_cast(parameter); + + if (options->GetDHCPEnable()) + { + std::function callback = ipObtained; + Dhcp::ObtainIp(callback); + } + else + { + // Try parsing the IP address in the options. + uint8_t ip[4]; + int scanned = sscanf( + options->GetIPAddress(), "%hhu.%hhu.%hhu.%hhu", &ip[3], &ip[2], &ip[1], &ip[0]); + + if (scanned == 4) + { + DEBUG_LOG("Setting IP address %d.%d.%d.%d\r\n", ip[3], ip[2], ip[1], ip[0]); + Utils::Ipv4Address = *reinterpret_cast(ip); + } + + ipObtained(); + } + } + + static void ipObtained() + { +#ifdef DEBUG + uint8_t* ip = reinterpret_cast(Utils::Ipv4Address); + DEBUG_LOG("Obtained IP address %d.%d.%d.%d\r\n", ip[3], ip[2], ip[1], ip[0]); +#endif + + Arp::SendAnnouncement(Utils::GetMacAddress(), Utils::Ipv4Address); + } +} // namespace Net diff --git a/src/net.h b/src/net.h index 321b87d..42475e5 100644 --- a/src/net.h +++ b/src/net.h @@ -1,5 +1,14 @@ #pragma once #include "net-arp.h" +#include "net-dhcp.h" #include "net-ethernet.h" #include "net-ipv4.h" #include "net-utils.h" + +#include "options.h" + +namespace Net +{ + void Initialize(Options& options); + void Update(); +} // namespace Net diff --git a/src/options.cpp b/src/options.cpp index 2774263..c973934 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -160,6 +160,8 @@ Options::Options(void) , buttonInsert(5) , rotaryEncoderEnable(0) //ROTARY: , rotaryEncoderInvert(0) //ROTARY: + , dhcpEnable(1) + , ipAddress{} { autoMountImageName[0] = 0; strcpy(ROMFontName, "chargen"); @@ -252,6 +254,7 @@ void Options::Process(char* buffer) ELSE_CHECK_DECIMAL_OPTION(buttonInsert) ELSE_CHECK_DECIMAL_OPTION(rotaryEncoderEnable) //ROTARY: ELSE_CHECK_DECIMAL_OPTION(rotaryEncoderInvert) //ROTARY: + ELSE_CHECK_DECIMAL_OPTION(dhcpEnable) else if ((strcasecmp(pOption, "AutoBaseName") == 0)) { strncpy(autoBaseName, pValue, 255); @@ -314,10 +317,14 @@ void Options::Process(char* buffer) { strncpy(ROMNameSlot8, pValue, 255); } - else if ((strcasecmp(pOption, "NewDiskType") == 0)) + else if (strcasecmp(pOption, "NewDiskType") == 0) { strncpy(newDiskType, pValue, 31); } + else if (strcasecmp(pOption, "IPAddress") == 0) + { + strncpy(ipAddress, pValue, sizeof(ipAddress) - 1); + } } if (!SplitIECLines()) diff --git a/src/options.h b/src/options.h index 889e4b9..5fd2e86 100644 --- a/src/options.h +++ b/src/options.h @@ -2,17 +2,17 @@ // Copyright(C) 2018 Stephen White // // This file is part of Pi1541. -// +// // Pi1541 is free software : you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // Pi1541 is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with Pi1541. If not, see . @@ -123,6 +123,9 @@ public: static unsigned GetDecimal(char* pString); static float GetFloat(char* pString); + constexpr int GetDHCPEnable() const { return dhcpEnable; } + constexpr const char* GetIPAddress() const { return ipAddress; } + private: unsigned int deviceID; unsigned int onResetChangeToStartingFolder; @@ -196,5 +199,8 @@ private: //ROTARY: Added for rotary encoder inversion (Issue#185) - 08/13/2020 by Geo... unsigned int rotaryEncoderInvert; + int dhcpEnable; + char ipAddress[16]; + }; #endif