From 960d8bc9897819885884f71aa7af60af195e8646 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 11:06:07 +0100 Subject: [PATCH 01/79] reimplementing the ethernet drivers --- libraries/Ethernet/src/Ethernet.cpp | 207 ------ libraries/Ethernet/src/EthernetC33.h | 63 +- libraries/Ethernet/src/EthernetDriver.cpp | 764 +++++++++++----------- libraries/Ethernet/src/EthernetDriver.h | 104 ++- 4 files changed, 477 insertions(+), 661 deletions(-) diff --git a/libraries/Ethernet/src/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp index 22c90ff6..0311f913 100644 --- a/libraries/Ethernet/src/Ethernet.cpp +++ b/libraries/Ethernet/src/Ethernet.cpp @@ -1,208 +1 @@ #include - -/* - * The old implementation of the begin set a default mac address: - * this does not make any sense. - * Default mac address is in the hardware, when lwip start that mac - * address is passed to lwip - * If mac address needs to be changed then call the appropriate function - * of lwIpIf before to get the interface - */ - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(unsigned long timeout, unsigned long responseTimeout) { -/* -------------------------------------------------------------------------- */ - (void)responseTimeout; - - int rv = 0; - - ni = CLwipIf::getInstance().get(NI_ETHERNET); - if(ni != nullptr) { - ni->DhcpSetTimeout(timeout); - rv = (int)ni->DhcpStart(); - } - - return rv; -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(IPAddress local_ip) { -/* -------------------------------------------------------------------------- */ - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns_server = local_ip; - dns_server[3] = 1; - return begin(local_ip, dns_server); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(IPAddress local_ip, IPAddress dns_server) { -/* -------------------------------------------------------------------------- */ - // Assume the gateway will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress gateway = local_ip; - gateway[3] = 1; - return begin(local_ip, dns_server, gateway); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { -/* -------------------------------------------------------------------------- */ - IPAddress subnet(255, 255, 255, 0); - return begin(local_ip, dns_server, gateway, subnet); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { -/* -------------------------------------------------------------------------- */ - - ni = CLwipIf::getInstance().get(NI_ETHERNET, local_ip, gateway, subnet); - if(ni == nullptr) { - return 0; - } - - /* If there is a local DHCP informs it of our manual IP configuration to prevent IP conflict */ - ni->DhcpNotUsed(); - CLwipIf::getInstance().addDns(dns_server); - return 1; -} - -/* -------------------------------------------------------------------------- */ -void CEthernet::setDNS(IPAddress dns_server) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().setMacAddress(NI_ETHERNET, mac); - return begin(timeout, responseTimeout); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(uint8_t *mac_address, IPAddress local_ip) { -/* -------------------------------------------------------------------------- */ - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns_server = local_ip; - dns_server[3] = 1; - return begin(mac_address, local_ip, dns_server); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server) { -/* -------------------------------------------------------------------------- */ - // Assume the gateway will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress gateway = local_ip; - gateway[3] = 1; - return begin(mac_address, local_ip, dns_server, gateway); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { -/* -------------------------------------------------------------------------- */ - IPAddress subnet(255, 255, 255, 0); - return begin(mac_address, local_ip, dns_server, gateway, subnet); -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet, unsigned long timeout, unsigned long responseTimeout) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().setMacAddress(NI_ETHERNET, mac); - return begin(local_ip, dns_server, gateway, subnet); -} - -/* -------------------------------------------------------------------------- */ -EthernetLinkStatus CEthernet::linkStatus() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return (!CLwipIf::getInstance().isEthInitialized()) ? Unknown : (ni->isLinkUp() ? LinkON : LinkOFF); - } - return Unknown; -} - -/* -------------------------------------------------------------------------- */ -EthernetHardwareStatus CEthernet::hardwareStatus() { -/* -------------------------------------------------------------------------- */ - return EthernetLwip; -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::disconnect() { -/* -------------------------------------------------------------------------- */ - return 1; -} - -/* -------------------------------------------------------------------------- */ -int CEthernet::maintain() { -/* -------------------------------------------------------------------------- */ - int rc = DHCP_CHECK_NONE; - - if (ni != NULL) { - //we have a pointer to dhcp, use it - rc = ni->checkLease(); - switch (rc) { - case DHCP_CHECK_NONE: - //nothing done - break; - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //_dnsServerAddress = _dhcp->getDnsServerIp(); - break; - default: - //this is actually a error, it will retry though - break; - } - } - return rc; -} - -/* - * This function updates the LwIP stack and can be called to be sure to update - * the stack (e.g. in case of a long loop). - */ -void CEthernet::schedule(void) { - if (ni != NULL) { - ni->task(); - } -} - - - -uint8_t *CEthernet::MACAddress(void) { - CLwipIf::getInstance().getMacAddress(NI_ETHERNET, mac_address); - return mac_address; -} - -void CEthernet::MACAddress(uint8_t *mac) { - CLwipIf::getInstance().getMacAddress(NI_ETHERNET, mac); -} - -IPAddress CEthernet::localIP() { - if(ni != nullptr) { - return IPAddress(ni->getIpAdd()); - } - return IPAddress((uint32_t)0); -} - -IPAddress CEthernet::subnetMask() { - if(ni != nullptr) { - return IPAddress(ni->getNmAdd()); - } - return IPAddress((uint32_t)0); -} - -IPAddress CEthernet::gatewayIP() { - if(ni != nullptr) { - return IPAddress(ni->getGwAdd()); - } - return IPAddress((uint32_t)0); -} - -IPAddress CEthernet::dnsServerIP() { - return CLwipIf::getInstance().getDns(); -} - -CEthernet Ethernet; diff --git a/libraries/Ethernet/src/EthernetC33.h b/libraries/Ethernet/src/EthernetC33.h index 97fa5451..b2b9e428 100644 --- a/libraries/Ethernet/src/EthernetC33.h +++ b/libraries/Ethernet/src/EthernetC33.h @@ -1,5 +1,4 @@ -#ifndef ARDUINO_C_ETHERNET_H -#define ARDUINO_C_ETHERNET_H +#pragma once #ifndef ARDUINO_PORTENTA_C33 // force discovering wth shield library @@ -13,65 +12,15 @@ #include "EthernetClient.h" #include "EthernetServer.h" +#include "EthernetDriver.h" #include "CNetIf.h" -#include "lwipMem.h" -enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF -}; +#ifdef ARDUINO_PORTENTA_C33 -enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetLwip = 7 -}; +// TODO Instantiate the drivers for ethernet with default configuration parameters +// EthernetC33Driver C33EthernetDriver(2, 2, mem_malloc, 1536); -class CEthernet { - - private: - CNetIf *ni; - - uint8_t mac_address[6]; - public: - // Initialise the Ethernet with the internal provided MAC address and gain the rest of the - // configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - EthernetLinkStatus linkStatus(); - int begin(IPAddress local_ip); - int begin(IPAddress local_ip, IPAddress dns_server); - int begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); - int begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); - // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the - // configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(uint8_t *mac_address, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - int begin(uint8_t *mac_address, IPAddress local_ip); - int begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); - int begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); - int begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - EthernetHardwareStatus hardwareStatus(); - - void setDNS(IPAddress dns_server); - - int disconnect(void); - int maintain(); - void schedule(void); - - - uint8_t *MACAddress(void); - void MACAddress(uint8_t *mac); - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - - friend class EthernetClient; - friend class EthernetServer; -}; - -extern CEthernet Ethernet; +// FIXME Instantiate a global variable from CEth, calling it Ethernet #endif diff --git a/libraries/Ethernet/src/EthernetDriver.cpp b/libraries/Ethernet/src/EthernetDriver.cpp index 70eaf43d..ae69c8a4 100644 --- a/libraries/Ethernet/src/EthernetDriver.cpp +++ b/libraries/Ethernet/src/EthernetDriver.cpp @@ -1,145 +1,73 @@ #include "EthernetDriver.h" -#include "IRQManager.h" +#include +#include +#include "utils.h" +#include -/* IMPORTANT NOTE: this driver is configured to use ZERO COPY - This means when a frame is received the Read function do not perform - a copy of the data bu just returns the pointer to them - */ - -#define USE_ZERO_COPY - - -typedef enum { - ETH_LINK_UP, - ETH_LINK_DOWN -} EthLinkStatus_t; - - - - - -#define ETHERNET_DEBUG_ENABLED 0 - -class EthernetDriver { -public: - EthernetDriver(); - bool enableIrq(uint32_t priority = 12); - - uint8_t mac_address[MAC_ADDRESS_DIM]; - /* ETHERNET PHY */ - ether_phy_cfg_t phy_cfg; - ether_phy_instance_ctrl_t phy_ctrl; - ether_phy_instance_t phy_instance; - - /* ETHERNET */ - ether_cfg_t cfg; - ether_instance_ctrl_t ctrl; - ether_extended_cfg_t extended_cfg; - - ether_cfg_t *get_cfg() {return &cfg;} - ether_instance_ctrl_t *get_ctrl() {return &ctrl;} - -private: - static EthLinkStatus_t link_status; - static void irq_callback(ether_callback_args_t * p_args); - #ifndef USE_ZERO_COPY - uint8_t *buffs[2]; - #else - uint8_t *buffs[1]; - #endif - - __attribute__((__aligned__(32)))uint8_t buffer0[ETH_BUFF_DIM] ; - #ifndef USE_ZERO_COPY - __attribute__((__aligned__(32)))uint8_t buffer1[ETH_BUFF_DIM] ; - #endif - - __attribute__((__aligned__(16))) ether_instance_descriptor_t tx_descriptors[1] ; - __attribute__((__aligned__(16))) ether_instance_descriptor_t rx_descriptors[1] ; - -}; +#define ETHERNET_PIN_CFG ((uint32_t) ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_ETHER_RMII)) #define ETHERNET_CHANNEL (0) - +#define ADE_BIT_MASK (1 << 23) #define ETHER_FRAME_RECEIVED_MASK (1UL << 18) #define ETHER_FRAME_TRANSFER_COMPLETED (1UL << 21) #define ETHER_MAGIC_PACKET_DETECTED_MASK (1UL << 1) +#define ETHER_RD0_RACT (0x80000000UL) + +// utility/proxy local functions +void _irq_ether_callback(ether_callback_args_t* p_args); + +extern void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks=4, uint8_t cols=16); + +EthernetC33Driver::EthernetC33Driver( + uint8_t rx_descriptors_len, + uint8_t tx_descriptors_len, + void* (*buffer_allocator)(unsigned int), + uint16_t buffer_size, + uint8_t* mac_address, uint8_t len) +: NetworkDriver(), +rx_descriptors_len(rx_descriptors_len), tx_descriptors_len(tx_descriptors_len), +buffer_allocator(buffer_allocator), buffer_size(buffer_size) { + if(mac_address != nullptr && (len == 6 || len == 8)) { + memcpy(this->macaddress, mac_address, len); + this->macaddress_len = len; + } else { + const bsp_unique_id_t* t = R_BSP_UniqueIdGet(); + this->macaddress[0] = 0xA8; + this->macaddress[1] = 0x61; + this->macaddress[2] = 0x0A; + this->macaddress[3] = t->unique_id_words[0] ^ t->unique_id_words[1]; + this->macaddress[4] = t->unique_id_words[2]; + this->macaddress[5] = t->unique_id_words[3]; + } -static volatile bool frame_being_transmitted = false; -static EthernetDriver eth_driver; + this->rx_descriptors = (ether_instance_descriptor_t*) + memalign(16, sizeof(ether_instance_descriptor_t)*rx_descriptors_len); + this->tx_descriptors = (ether_instance_descriptor_t*) + memalign(16, sizeof(ether_instance_descriptor_t)*tx_descriptors_len); + // memalign(16, sizeof(ether_instance_descriptor_t)*1); -static uint8_t eth_tx_buffer[ETH_BUFF_DIM]; + rx_buffers = (uint8_t**) malloc(sizeof(void*)*rx_descriptors_len); -uint8_t *eth_get_tx_buffer(uint16_t *size) { - *size = ETH_BUFF_DIM; - return eth_tx_buffer; + tx_buffers_info = (_tx_buffer_info*) malloc(sizeof(_tx_buffer_info)*tx_descriptors_len); + memset(tx_buffers_info, 0, sizeof(_tx_buffer_info)*tx_descriptors_len); + + this->init(); } +EthernetC33Driver::~EthernetC33Driver() { + free(this->rx_descriptors); + this->rx_descriptors = nullptr; + free(this->tx_descriptors); + this->tx_descriptors = nullptr; -#define ETHERNET_PIN_CFG ((uint32_t) ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_ETHER_RMII)) + // TODO free memory of buffers, callback with size 0? + // this->rx_buffers + // this->tx_buffers +} -/* -------------------------------------------------------------------------- */ -EthernetDriver::EthernetDriver() { -/* -------------------------------------------------------------------------- */ - - /* default MAC ADDRESS */ - const bsp_unique_id_t* t = R_BSP_UniqueIdGet(); - mac_address[0] = 0xA8; - mac_address[1] = 0x61; - mac_address[2] = 0x0A; - mac_address[3] = t->unique_id_words[0] ^ t->unique_id_words[1]; - mac_address[4] = t->unique_id_words[2]; - mac_address[5] = t->unique_id_words[3]; - - /* ethernet PHY _________________________________________________________ */ - phy_cfg.channel = ETHERNET_CHANNEL; - phy_cfg.phy_lsi_address = 0; - phy_cfg.phy_reset_wait_time = 0x00020000; - phy_cfg.mii_bit_access_wait_time = 8; - phy_cfg.phy_lsi_type = ETHER_PHY_LSI_TYPE_DEFAULT; - phy_cfg.flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE; - phy_cfg.mii_type = ETHER_PHY_MII_TYPE_RMII; - phy_cfg.p_context = nullptr; - phy_cfg.p_extend = nullptr; - /* ethernet PHY instance (used by ethernet, below) ______________________ */ - phy_instance.p_cfg = &phy_cfg; - phy_instance.p_ctrl = &phy_ctrl; - phy_instance.p_api = &g_ether_phy_on_ether_phy; - /* ethernet _____________________________________________________________ */ - extended_cfg.p_rx_descriptors = rx_descriptors; - extended_cfg.p_tx_descriptors = tx_descriptors; - - - buffs[0] = buffer0; - #ifndef USE_ZERO_COPY - buffs[1] = buffer1; - #endif - cfg.channel = ETHERNET_CHANNEL; - #ifndef USE_ZERO_COPY - cfg.zerocopy = ETHER_ZEROCOPY_DISABLE; - #else - cfg.zerocopy = ETHER_ZEROCOPY_ENABLE; - #endif - cfg.multicast = ETHER_MULTICAST_ENABLE; - cfg.promiscuous = ETHER_PROMISCUOUS_DISABLE; - cfg.flow_control = ETHER_FLOW_CONTROL_DISABLE; - cfg.padding = ETHER_PADDING_DISABLE; - cfg.padding_offset = 0; - cfg.broadcast_filter = 0; - cfg.p_mac_address = mac_address; - //cfg.p_rx_descriptors = rx_descriptors; - //cfg.p_tx_descriptors = tx_descriptors; - cfg.num_tx_descriptors = 1; - cfg.num_rx_descriptors = 1; - cfg.pp_ether_buffers = buffs; - cfg.ether_buffer_size = ETH_BUFF_DIM; - cfg.irq = FSP_INVALID_VECTOR; - cfg.interrupt_priority = (12); - cfg.p_callback = irq_callback; - cfg.p_ether_phy_instance = &phy_instance; - cfg.p_context = nullptr; - cfg.p_extend = &extended_cfg; - /* PIN configuration ____________________________________________________ */ - +void EthernetC33Driver::init() { + // FIXME understand the configuration performed here + // FIXME understand how to pass this configuration as a parameter R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_14, ETHERNET_PIN_CFG); R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_11, ETHERNET_PIN_CFG); R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, ETHERNET_PIN_CFG); @@ -150,304 +78,390 @@ EthernetDriver::EthernetDriver() { R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_07_PIN_03, ETHERNET_PIN_CFG); R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_07_PIN_04, ETHERNET_PIN_CFG); R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_07_PIN_05, ETHERNET_PIN_CFG); - //R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_07_PIN_04, ETHERNET_PIN_CFG); + + // phy setup + this->phy_cfg.channel = ETHERNET_CHANNEL; + this->phy_cfg.phy_lsi_address = 0; + this->phy_cfg.phy_reset_wait_time = 0x00020000; + this->phy_cfg.mii_bit_access_wait_time = 8; + this->phy_cfg.phy_lsi_type = ETHER_PHY_LSI_TYPE_DEFAULT; + this->phy_cfg.flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE; + this->phy_cfg.mii_type = ETHER_PHY_MII_TYPE_RMII; + this->phy_cfg.p_context = nullptr; + this->phy_cfg.p_extend = nullptr; + + this->phy_instance.p_cfg = &this->phy_cfg; + this->phy_instance.p_ctrl = &this->phy_ctrl; + this->phy_instance.p_api = &g_ether_phy_on_ether_phy; + + // setup the driver + this->extended_cfg.p_rx_descriptors = this->rx_descriptors; // FIXME + this->extended_cfg.p_tx_descriptors = this->tx_descriptors; // FIXME + + + this->cfg.channel = ETHERNET_CHANNEL; + this->cfg.zerocopy = ETHER_ZEROCOPY_ENABLE; + this->cfg.multicast = ETHER_MULTICAST_ENABLE; + this->cfg.promiscuous = ETHER_PROMISCUOUS_DISABLE; + this->cfg.flow_control = ETHER_FLOW_CONTROL_DISABLE; + this->cfg.padding = ETHER_PADDING_DISABLE; // TODO + this->cfg.padding_offset = 0; + this->cfg.broadcast_filter = 0; + this->cfg.p_mac_address = this->macaddress; + this->cfg.num_tx_descriptors = this->tx_descriptors_len; + this->cfg.num_rx_descriptors = this->rx_descriptors_len; + this->cfg.pp_ether_buffers = this->rx_buffers; + this->cfg.ether_buffer_size = this->buffer_size; + this->cfg.irq = FSP_INVALID_VECTOR; + this->cfg.interrupt_priority = (this->irq_priority); + this->cfg.p_callback = _irq_ether_callback; + this->cfg.p_ether_phy_instance = &this->phy_instance; + this->cfg.p_context = this; + this->cfg.p_extend = &this->extended_cfg; } -/* -------------------------------------------------------------------------- */ -bool EthernetDriver::enableIrq(uint32_t priority /*== 12*/) { -/* -------------------------------------------------------------------------- */ - bool rv = IRQManager::getInstance().addPeripheral(IRQ_ETHERNET,&cfg); - if(rv) { - cfg.interrupt_priority = priority; - R_BSP_IrqCfgEnable(cfg.irq, cfg.interrupt_priority, &ctrl); /* ??? */ +void EthernetC33Driver::begin() { + // Fill the rx_buffers + uint8_t i=0; + for(; i < rx_descriptors_len; i++) { + // buffer_allocator has to take into account memory alignment + rx_buffers[i] = (uint8_t*)buffer_allocator(buffer_size); + + if(rx_buffers[i] == nullptr) { + break; + } + } + + // If at least a buffer is allocated, wait for the link to be up, otherwise report an error + // TODO report error + if(i > 0) { + this->up(); } - return rv; } -EthLinkStatus_t EthernetDriver::link_status = ETH_LINK_DOWN; -EtherCallback_f frame_received = nullptr; -EtherCallback_f frame_transmitted = nullptr; -EtherCallback_f magic_packet_received = nullptr; -EtherCallback_f link_on = nullptr; -EtherCallback_f link_off = nullptr; -EtherCallback_f lan_wake_up = nullptr; +void EthernetC33Driver::poll() { + // Polling the rx descriptor for available data -#define ADE_BIT_MASK (1 << 23) + uint32_t rx_frame_dim = 0; + uint8_t* rx_frame_buf = nullptr; + fsp_err_t err = FSP_SUCCESS; + struct pbuf *p = nullptr; -/* This function performs a sort of reset of the EDMAC and Ethernet controller - when the ADE bit in EESR EDMAC register is 1 - (however it does not solve the problem since the cause of this in unkknown)*/ + if(this->consume_cbk == nullptr) { + // Callback is not set, no meaning to release buffers + // TODO put assertion + return; + } -/* -------------------------------------------------------------------------- */ -void eth_reset_due_to_ADE_bit() { -/* -------------------------------------------------------------------------- */ - uint32_t *EDMAC_EESR_REG = (uint32_t *)0x40114028; - uint32_t *EDMAC_CONTROL_REG = (uint32_t *)0x40114000; - if( (*EDMAC_EESR_REG & ADE_BIT_MASK) == ADE_BIT_MASK) { - R_ETHER_Close(eth_driver.get_ctrl()); - *EDMAC_CONTROL_REG |= 0x1; - R_ETHER_Open(eth_driver.get_ctrl(), eth_driver.get_cfg()); - } -} + netif_stats &stats = *(this->stats); + NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(stats); + // arduino::lock(); + while(ETHER_RD0_RACT != (ctrl.p_rx_descriptor->status & ETHER_RD0_RACT)) { + NETIF_STATS_RX_TIME_START(stats); // FIXME add stats + // Getting the available data in the Eth DMA buffer + err = R_ETHER_Read(&this->ctrl, &rx_frame_buf, &rx_frame_dim); + // DEBUG_INFO("[polling] read %08X, %u, %u", rx_frame_buf, rx_frame_dim, err); + if(err != FSP_SUCCESS) { + NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(stats); + NETIF_STATS_INCREMENT_ERROR(stats, err); + NETIF_STATS_RX_TIME_AVERAGE(stats); -/* -------------------------------------------------------------------------- */ -void EthernetDriver::irq_callback(ether_callback_args_t * p_args) { -/* -------------------------------------------------------------------------- */ - p_args->status_ecsr; - uint32_t reg_eesr = p_args->status_eesr; - if(p_args->channel == ETHERNET_CHANNEL) { - if(p_args->event == ETHER_EVENT_WAKEON_LAN) { - - /* WAKE ON */ - if(lan_wake_up != nullptr) { - lan_wake_up(); - } - } - else if(p_args->event == ETHER_EVENT_LINK_ON) { - - /* LINK ON */ - if(link_on != nullptr) { - link_on(); - } + // Error, discarding the buffer without consuming it + R_ETHER_BufferRelease(&ctrl); + break; } - else if(p_args->event == ETHER_EVENT_LINK_OFF) { - - /* LINK OFF */ - if(link_off != nullptr) { - link_off(); - } + + // giving the ownership of the buffer to the module using the driver, + // this memory should be now handled by the new owner + if(!this->consumed) { + // DEBUG_INFO("buf %8X", rx_frame_buf); + this->consume_cbk(rx_frame_buf, rx_frame_dim); } - else if(p_args->event == ETHER_EVENT_INTERRUPT) { - if (ETHER_MAGIC_PACKET_DETECTED_MASK == (p_args->status_ecsr & ETHER_MAGIC_PACKET_DETECTED_MASK)) { - - /* MAGIC PACKET DETECTED */ - if(magic_packet_received != nullptr) { - magic_packet_received(); - } - } - if (ETHER_FRAME_TRANSFER_COMPLETED == (reg_eesr & ETHER_FRAME_TRANSFER_COMPLETED)) { - - - frame_being_transmitted = false; - /* FRAME TRANSMISSION COMPLETED */ - if(frame_transmitted != nullptr) { - frame_transmitted(); - } - } - if (ETHER_FRAME_RECEIVED_MASK == (reg_eesr & ETHER_FRAME_RECEIVED_MASK)) { - - /* FRAME RECEIVED */ - if(frame_received != nullptr) { - frame_received(); - } - } - if( (reg_eesr & ADE_BIT_MASK) == ADE_BIT_MASK) { - /* weird error with ADE bit set as soon as reception is enabled */ - eth_reset_due_to_ADE_bit(); - } + + // TODO find a way to put a limit into the number of mem_malloc + arduino::lock(); + uint8_t* new_buffer = (uint8_t*)buffer_allocator(buffer_size); + arduino::unlock(); + + if(new_buffer == nullptr) { + this->consumed = true; // this indicates that the buffer had been consumed, but the new buffer isn't allocated + break; + } else { + this->consumed = false; // this indicates that the buffer had been consumed and the new buffer is allocated } - else { - + err = R_ETHER_RxBufferUpdate(&ctrl, new_buffer); + NETIF_STATS_INCREMENT_ERROR(stats, err); + NETIF_STATS_RX_TIME_AVERAGE(stats); + if(err != FSP_SUCCESS) { + // DEBUG_INFO("%u", err); // FIXME handle this } } + // arduino::unlock(); + + // Polling the tx descriptor for Tx transmission completed + // while(R_ETHER_TxStatusGet(this->ctrl, tx_buffers_info[first].buffer) { + // // FIXME check that first and the completed packet are valid + // // FIXME move this into the poll function + // tx_buffers_info[first].len = 0; + + // if(tx_buffers_info[first].free_function) { + // tx_buffers_info[first].free_function(tx_buffers_info[first].buffer); + // tx_buffers_info[first].free_function = nullptr; + // } else { + // free(tx_buffers_info[first].buffer); + // } + // tx_buffers_info[first].buffer = nullptr; + // first = (first + 1) % tx_descriptors_len; + // } } -/* -------------------------------------------------------------------------- */ -void eth_set_mac_address(const uint8_t *mad) { -/* -------------------------------------------------------------------------- */ - for(int i = 0; i < MAC_ADDRESS_DIM; i++) { - eth_driver.mac_address[i] = *(mad + i); +network_driver_send_err_t EthernetC33Driver::send( + uint8_t* data, uint16_t len, network_driver_send_flags_t flags, void(*free_function)(void*)) { + // dump_buffer(tx_buffers_info[last].buffer, len); + // dump_buffer(data, len); + // DEBUG_INFO("[send] %08X, %u", data, len); + network_driver_send_err_t res = NETWORK_DRIVER_SEND_ERR_OK; + fsp_err_t err; + + arduino::lock(); + // the current buffer we are referencing is not yet consumed + if(this->tx_buffers_info[this->last].len != 0) { + res = NETWORK_DRIVER_SEND_ERR_BUFFER; + goto exit; } -} -/* -------------------------------------------------------------------------- */ -int eth_get_mac_address(uint8_t *mad) { -/* -------------------------------------------------------------------------- */ - for(int i = 0; i < MAC_ADDRESS_DIM; i++) { - *(mad + i) = eth_driver.mac_address[i]; - } - return MAC_ADDRESS_DIM; -} + if(flags == NETWORK_DRIVER_SEND_FLAGS_NONE) { + // it could be nice to use buffer_allocator, but we need a way to deallocate it + this->tx_buffers_info[this->last].buffer = (uint8_t*)memalign(32, len); // TODO does this need to be memaligned? I think not + if(this->tx_buffers_info[this->last].buffer == nullptr) { + res = NETWORK_DRIVER_SEND_ERR_BUFFER; + goto exit; + } -/* -------------------------------------------------------------------------- */ -bool eth_init() { -/* -------------------------------------------------------------------------- */ - bool rv = false; - - if(!eth_driver.enableIrq(ETHERNET_IRQ_PRIORITY)) { - return rv; + // perform a memcpy to the local tx_buffer + memcpy(this->tx_buffers_info[this->last].buffer, data, len); + } else if(flags == NETWORK_DRIVER_SEND_FLAGS_ZERO_COPY) { + this->tx_buffers_info[this->last].buffer = data; // FIXME verify this mode } + this->tx_buffers_info[this->last].len = len; + this->tx_buffers_info[this->last].free_function = free_function; - /* ---- - * open - * ---- */ - fsp_err_t err = R_ETHER_Open(eth_driver.get_ctrl(), eth_driver.get_cfg()); - - /* - uint32_t *reg = (uint32_t *)0x40114118; - *reg = 0x37; - reg = (uint32_t *)0x40114030; - *reg = 0x47FF099F; - */ - if(err == FSP_SUCCESS) { - rv = true; - } - #ifdef ETHERNET_DEBUG_ENABLED - else if(err == FSP_ERR_ALREADY_OPEN) { - rv = false; - } - else if(err == FSP_ERR_ETHER_ERROR_PHY_COMMUNICATION) { - rv = false; - } - else if(err == FSP_ERR_ETHER_PHY_ERROR_LINK) { - rv = false; + // dump_buffer(this->tx_buffers_info[this->last].buffer, len); + // dump_buffer(data, len); + + // put this buffer in the next circular buffer position and then increment the index + // TODO handle the case where a packet is already being transmitted, should WRITE be called after the queued packet is correctly sent? + err = R_ETHER_Write( + &this->ctrl, this->tx_buffers_info[this->last].buffer, this->tx_buffers_info[this->last].len); + this->last = (this->last + 1) % this->tx_descriptors_len; + if(err != FSP_SUCCESS) { + res = NETWORK_DRIVER_SEND_ERR_DRIVER; } - #endif - - - - #ifdef IGMP_HARDWARE_LEVEL - /* CODE TO BE VERIFIED */ - #if LWIP_IGMP - netif_set_igmp_mac_filter(netif, igmp_mac_filter); - #endif - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_IMR, ®value); - - regvalue |= PHY_ISFR_INT4; - - /* Enable Interrupt on change of link status */ - HAL_ETH_WritePHYRegister(&EthHandle, PHY_IMR, regvalue); - #if LWIP_IGMP - ETH_HashTableHigh = EthHandle.Instance->MACHTHR; - ETH_HashTableLow = EthHandle.Instance->MACHTLR; - #endif - #endif - - return rv; -} -void eth_execute_link_process() { - R_ETHER_LinkProcess(eth_driver.get_ctrl()); +exit: + arduino::unlock(); + return res; } -void eth_release_rx_buffer() { - R_ETHER_BufferRelease(eth_driver.get_ctrl()); -} +fsp_err_t EthernetC33Driver::open() { + bool rv = IRQManager::getInstance().addPeripheral(IRQ_ETHERNET, &cfg); + if(rv) { + // cfg.interrupt_priority = irq_priority; + R_BSP_IrqCfgEnable(cfg.irq, cfg.interrupt_priority, &this->ctrl); /* ??? */ + } else { + // DEBUG_ERROR("Error setting up irq for ethernet"); + // return -1000; // FIXME error codes should be defined at ArduinoAPI level + return FSP_ERR_ABORTED; + } -bool eth_output(uint8_t *buf, uint16_t dim) { - bool retval = true; + return R_ETHER_Open(&this->ctrl, &this->cfg); +} - fsp_err_t err = R_ETHER_Write(eth_driver.get_ctrl(), buf, dim); - if(err == FSP_SUCCESS) { - frame_being_transmitted = true; - retval = true; - } - else { - retval = false; +void EthernetC33Driver::up() { + fsp_err_t err = FSP_SUCCESS; + + err = this->open(); + + if(err != FSP_SUCCESS) { + // return err; } - return retval; + do { + err = this->linkProcess(); + // TODO check if error assumes values that are not correct + // TODO put a timeout in here + } while(err != FSP_SUCCESS); + + // return err; // FIXME find a proper way of returning an error } -// this function return true if the tx buffer is not being used for the transmission of another frame -bool eth_output_can_transimit() { - return !frame_being_transmitted; +void EthernetC33Driver::down() { + // return + // FIXME implement this } -uint8_t *eth_input(volatile uint32_t *dim) { - /* NOTE: ZERO COPY IMPLEMENTATION - just the pointer and not the data are copied with the Read Function */ - - uint8_t *ptr1 = nullptr; +fsp_err_t EthernetC33Driver::linkProcess() { + return R_ETHER_LinkProcess(&this->ctrl); +} - fsp_err_t err = R_ETHER_Read ( eth_driver.get_ctrl(), &ptr1, (uint32_t *)dim); - if(err == FSP_SUCCESS) { - return ptr1; - } - else { - return nullptr; + +void EthernetC33Driver::eth_reset_due_to_ADE_bit() { + uint32_t *EDMAC_EESR_REG = (uint32_t *)0x40114028; + uint32_t *EDMAC_CONTROL_REG = (uint32_t *)0x40114000; + if( (*EDMAC_EESR_REG & ADE_BIT_MASK) == ADE_BIT_MASK) { + R_ETHER_Close(&this->ctrl); + *EDMAC_CONTROL_REG |= 0x1; + R_ETHER_Open(&this->ctrl, &this->cfg); } } +void EthernetC33Driver::irq_ether_callback(ether_callback_args_t* p_args) { + // ether_callback_args_t* p_args = (ether_callback_args_t*) args; + p_args->status_ecsr; + uint32_t reg_eesr = p_args->status_eesr; + + if(p_args->channel == ETHERNET_CHANNEL) { + if(p_args->event == ETHER_EVENT_WAKEON_LAN) { + /* WAKE ON */ + if(this->wake_lan_cbk != nullptr) { + this->wake_lan_cbk(); + } + } else if(p_args->event == ETHER_EVENT_LINK_ON) { + // /* LINK ON */ + if(this->link_up_cbk != nullptr) { + this->link_up_cbk(); + } + } else if(p_args->event == ETHER_EVENT_LINK_OFF) { + /* LINK OFF */ + if(this->link_down_cbk != nullptr) { + this->link_down_cbk(); + } + } else if(p_args->event == ETHER_EVENT_INTERRUPT) { + if (ETHER_MAGIC_PACKET_DETECTED_MASK == (p_args->status_ecsr & ETHER_MAGIC_PACKET_DETECTED_MASK)) { + // /* MAGIC PACKET DETECTED */ + if(this->magic_packet_cbk != nullptr) { + this->magic_packet_cbk(); + } + } + if (ETHER_FRAME_TRANSFER_COMPLETED == (reg_eesr & ETHER_FRAME_TRANSFER_COMPLETED)) { -void eth_set_rx_frame_cbk (EtherCallback_f fn) { frame_received = fn; } -void eth_set_tx_frame_cbk (EtherCallback_f fn) { frame_transmitted = fn; } -void eth_set_link_on_cbk (EtherCallback_f fn) { link_on = fn; } -void eth_set_link_off_cbk (EtherCallback_f fn) { link_off = fn; } -void eth_set_lan_wake_up_cbk (EtherCallback_f fn) { lan_wake_up = fn;} -void eth_set_magic_packet_cbk(EtherCallback_f fn) { magic_packet_received = fn;} + // FIXME check that first and the completed packet are valid + // FIXME move this into the poll function + // FIXME define a function out of this + if(tx_buffers_info[first].len == 0 || tx_buffers_info[first].buffer == nullptr) { + return; + } + arduino::lock(); + if(tx_buffers_info[first].free_function) { + tx_buffers_info[first].free_function(tx_buffers_info[first].buffer); + tx_buffers_info[first].free_function = nullptr; + } else { + free(tx_buffers_info[first].buffer); + } + tx_buffers_info[first].len = 0; + tx_buffers_info[first].buffer = nullptr; + first = (first + 1) % tx_descriptors_len; + arduino::unlock(); -#ifdef IGMP_HARDWARE_LEVEL -#if LWIP_IGMP -#ifndef HASH_BITS -#define HASH_BITS 6 /* #bits in hash */ -#endif -uint32_t ethcrc(const uint8_t *data, size_t length) -{ - uint32_t crc = 0xffffffff; - size_t i; - int j; + if(this->tx_frame_cbk != nullptr) { + this->tx_frame_cbk(); + } + } + if (ETHER_FRAME_RECEIVED_MASK == (reg_eesr & ETHER_FRAME_RECEIVED_MASK)) { + /* FRAME RECEIVED */ - for (i = 0; i < length; i++) { - for (j = 0; j < 8; j++) { - if (((crc >> 31) ^ (data[i] >> j)) & 0x01) { - /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ - crc = (crc << 1) ^ 0x04C11DB7; - } else { - crc = crc << 1; - } + // We are using polling mode, we don't need this + } + if (ADE_BIT_MASK == (reg_eesr & ADE_BIT_MASK)) { + /* weird error with ADE bit set as soon as reception is enabled */ + this->eth_reset_due_to_ADE_bit(); + } + } } - } - return ~crc; -} - -void register_multicast_address(const uint8_t *mac) -{ - uint32_t crc; - uint8_t hash; - - /* Calculate crc32 value of mac address */ - crc = ethcrc(mac, HASH_BITS); - - /* - * Only upper HASH_BITS are used - * which point to specific bit in the hash registers - */ - hash = (crc >> 26) & 0x3F; - - if (hash > 31) { - ETH_HashTableHigh |= 1 << (hash - 32); - EthHandle.Instance->MACHTHR = ETH_HashTableHigh; - } else { - ETH_HashTableLow |= 1 << hash; - EthHandle.Instance->MACHTLR = ETH_HashTableLow; - } } -err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action) -{ - uint8_t mac[6]; - const uint8_t *p = (const uint8_t *)ip4_addr; +void _irq_ether_callback(ether_callback_args_t* p_args) { + // _IRQEtherHandler* context = (_IRQEtherHandler*)p_args->p_context; + // dynamic_cast<_IRQEtherHandler*>(p_args->p_context); + EthernetC33Driver* context = + // dynamic_cast(p_args->p_context); + (EthernetC33Driver*)p_args->p_context; - mac[0] = 0x01; - mac[1] = 0x00; - mac[2] = 0x5E; - mac[3] = *(p + 1) & 0x7F; - mac[4] = *(p + 2); - mac[5] = *(p + 3); - - register_multicast_address(mac); - - return 0; + context->irq_ether_callback(p_args); } -#endif /* LWIP_IGMP */ -#endif + +// #ifdef IGMP_HARDWARE_LEVEL +// #if LWIP_IGMP +// #ifndef HASH_BITS +// #define HASH_BITS 6 /* #bits in hash */ +// #endif +// FIXME integrate these functions correctly into the library +// uint32_t ethcrc(const uint8_t *data, size_t length) +// { +// uint32_t crc = 0xffffffff; +// size_t i; +// int j; + +// for (i = 0; i < length; i++) { +// for (j = 0; j < 8; j++) { +// if (((crc >> 31) ^ (data[i] >> j)) & 0x01) { +// /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ +// crc = (crc << 1) ^ 0x04C11DB7; +// } else { +// crc = crc << 1; +// } +// } +// } +// return ~crc; +// } + +// void register_multicast_address(const uint8_t *mac) +// { +// uint32_t crc; +// uint8_t hash; + +// /* Calculate crc32 value of mac address */ +// crc = ethcrc(mac, HASH_BITS); + +// /* +// * Only upper HASH_BITS are used +// * which point to specific bit in the hash registers +// */ +// hash = (crc >> 26) & 0x3F; + +// if (hash > 31) { +// ETH_HashTableHigh |= 1 << (hash - 32); +// EthHandle.Instance->MACHTHR = ETH_HashTableHigh; +// } else { +// ETH_HashTableLow |= 1 << hash; +// EthHandle.Instance->MACHTLR = ETH_HashTableLow; +// } +// } + +// err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action) +// { +// uint8_t mac[6]; +// const uint8_t *p = (const uint8_t *)ip4_addr; + +// mac[0] = 0x01; +// mac[1] = 0x00; +// mac[2] = 0x5E; +// mac[3] = *(p + 1) & 0x7F; +// mac[4] = *(p + 2); +// mac[5] = *(p + 3); + +// register_multicast_address(mac); + +// return 0; +// } +// #endif /* LWIP_IGMP */ +// #endif diff --git a/libraries/Ethernet/src/EthernetDriver.h b/libraries/Ethernet/src/EthernetDriver.h index 18cf68f9..8af05d6c 100644 --- a/libraries/Ethernet/src/EthernetDriver.h +++ b/libraries/Ethernet/src/EthernetDriver.h @@ -1,38 +1,98 @@ -#ifndef _ARDUINO_RENESAS_ETHERNET_DRIVER_ -#define _ARDUINO_RENESAS_ETHERNET_DRIVER_ +#pragma once #include "r_ether_phy_api.h" #include "r_ether_phy.h" #include "r_ether_api.h" #include "r_ether.h" #include +#include -using EtherCallback_f = std::function; +class EthernetC33Driver: public NetworkDriver { +public: + EthernetC33Driver( + uint8_t rx_descriptors_len=1, + uint8_t tx_descriptors_len=1, + void* (*buffer_allocator)(unsigned int)=malloc, // The allocator should return 16 byte aligned + uint16_t buffer_size=1536, + uint8_t* mac_address=nullptr, uint8_t len=0); // TODO provide pinmapping as parameter to the constructor + ~EthernetC33Driver(); -#define ETHERNET_IRQ_PRIORITY 10 + /* + * TODO define the meaning of begin: open + link up? + */ + virtual void begin(); -#define MAC_ADDRESS_DIM 6 -#define ETH_BUFF_DIM 1536 + // Provide a function to poll the driver + virtual void poll(); + virtual fsp_err_t open(); // FIXME errors should be abstracted + virtual fsp_err_t linkProcess(); + virtual void up(); + virtual void down(); -/* set the MAC ADDRESS, use the function before the initialization */ -void eth_set_mac_address(const uint8_t *mad); -int eth_get_mac_address(uint8_t *mad); + virtual network_driver_send_err_t send(uint8_t* data, uint16_t len, + network_driver_send_flags_t flags=NETWORK_DRIVER_SEND_FLAGS_NONE, + void(*free_function)(void*)=nullptr); -bool eth_init(); -void eth_execute_link_process(); -uint8_t *eth_input(volatile uint32_t *dim); -bool eth_output(uint8_t *buf, uint16_t dim); -bool eth_output_can_transimit(); -void eth_release_rx_buffer(); -uint8_t *eth_get_tx_buffer(uint16_t *size); -void eth_set_rx_frame_cbk(EtherCallback_f fn); -void eth_set_tx_frame_cbk(EtherCallback_f fn); -void eth_set_link_on_cbk(EtherCallback_f fn); -void eth_set_link_off_cbk(EtherCallback_f fn); -void eth_set_lan_wake_up_cbk(EtherCallback_f fn); -void eth_set_magic_packet_cbk(EtherCallback_f fn); + // TODO add callbacks getters/setters + virtual uint8_t* getMacAddress() override { return this->macaddress; } +protected: + // extend the callbacks and add the Driver specific callbacks + std::function wake_lan_cbk; + std::function magic_packet_cbk; + +private: + ether_instance_descriptor_t *tx_descriptors; + ether_instance_descriptor_t *rx_descriptors; + + uint8_t **rx_buffers; + + // array containing the info of the buffers queued to be sent + struct _tx_buffer_info { + uint16_t len=0; + uint8_t* buffer=nullptr; + void(*free_function)(void*)=nullptr; + }; + _tx_buffer_info *tx_buffers_info; + + // tx circular buffer cursors + uint8_t last = 0, first=0; + + // uint8_t tx_buffer[1536]; + volatile bool frame_in_transmission = false; + + uint8_t macaddress[8]; // FIXME differentiate between 6 and 8 len + uint8_t macaddress_len = 0; + + // FSP structures for control and configuration of the driver + ether_phy_cfg_t phy_cfg; + ether_phy_instance_ctrl_t phy_ctrl; + ether_phy_instance_t phy_instance; + ether_cfg_t cfg; + ether_instance_ctrl_t ctrl; + ether_extended_cfg_t extended_cfg; + const uint32_t irq_priority = 10; + + uint8_t rx_descriptors_len; + uint8_t tx_descriptors_len; + void* (*buffer_allocator)(unsigned int); + uint16_t buffer_size; + + bool consumed = false; + + // This function initializes the driver and its configuration + // TODO provide a way for the user to override the settings + void init(); + + // Strange function that needs to be present, for whatever reason, keeping it + void eth_reset_due_to_ADE_bit(); + + virtual void irq_ether_callback(ether_callback_args_t* p_args); + friend void _irq_ether_callback(ether_callback_args_t* p_args); #endif +}; + +extern EthernetC33Driver C33EthernetDriver; \ No newline at end of file From 452accfed2a111aeba71b0894dde24ea2d202d76 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 11:07:12 +0100 Subject: [PATCH 02/79] added library containing abstract network stack classes --- libraries/NetworkAPI/library.properties | 9 +++ libraries/NetworkAPI/src/driver.h | 74 +++++++++++++++++++++++++ libraries/NetworkAPI/src/interface.h | 1 + 3 files changed, 84 insertions(+) create mode 100644 libraries/NetworkAPI/library.properties create mode 100644 libraries/NetworkAPI/src/driver.h create mode 100644 libraries/NetworkAPI/src/interface.h diff --git a/libraries/NetworkAPI/library.properties b/libraries/NetworkAPI/library.properties new file mode 100644 index 00000000..1f161d41 --- /dev/null +++ b/libraries/NetworkAPI/library.properties @@ -0,0 +1,9 @@ +name=NetworkAPI +version=1.0.0 +author=Arduino, Andrea Gilardoni +maintainer=Arduino +sentence=Definition of Network classes shared among different types of network interfaces +paragraph=This library contains the definition of the abstract classes used in the networking stack +category=Communication +url=https://github.com/arduino/ArduinoCore-renesas/tree/master/libraries/NetworkAPI +architectures=renesas,renesas_portenta diff --git a/libraries/NetworkAPI/src/driver.h b/libraries/NetworkAPI/src/driver.h new file mode 100644 index 00000000..3b347f77 --- /dev/null +++ b/libraries/NetworkAPI/src/driver.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include + +enum network_driver_send_flags_t: uint8_t { + NETWORK_DRIVER_SEND_FLAGS_NONE = 0, + // this option instructs the send function that it doesn't need to perform a memcpy to the passed argument + // and is in charge of deleting the buffer + NETWORK_DRIVER_SEND_FLAGS_ZERO_COPY = 1 +}; + +enum network_driver_send_err_t: uint8_t { + NETWORK_DRIVER_SEND_ERR_OK = 0, + NETWORK_DRIVER_SEND_ERR_MEM = 1, // memory issues when trying to send a packet + NETWORK_DRIVER_SEND_ERR_BUFFER = 2, // there is no available buffer for sending the packet + NETWORK_DRIVER_SEND_ERR_DRIVER = 3 // generic error happening at fsp level +}; + + +class NetworkDriver { +public: + NetworkDriver() {}; + virtual ~NetworkDriver() {}; + + /* + * This function is used by the Interface handling the driver, + * if used in polling mode, leave empty definition if the driver works though interrupts. + * When working with interrupts it is expected that the constructor definces them + */ + virtual void poll() {}; // TODO is it better to have a function pointer, that when set to null is not called? + + /* + * This function is used to inistialize the driver at runtime and start using it + */ + virtual void begin() = 0; + + /* + * this function is used to send data to the network + * + flags are used to specify additional options when sending + * + when NETWORK_DRIVER_SEND_FLAGS_ZERO_COPY is provided, a free function must be passed, [default libc free()] + */ + virtual network_driver_send_err_t send(uint8_t* data, uint16_t len, + network_driver_send_flags_t flags=NETWORK_DRIVER_SEND_FLAGS_NONE, + void(*free_function)(void*)=free) = 0; + + /* + * Sets the callback funtion that is then used to consume incoming data + */ + virtual void setConsumeCallback(std::function consume_cbk) {this->consume_cbk = consume_cbk;} + virtual void setLinkUpCallback(std::function link_up_cbk) {this->link_up_cbk = link_up_cbk;} + virtual void setLinkDownCallback(std::function link_down_cbk) {this->link_down_cbk = link_down_cbk;} + + /* + * FIXME define interfaces for RX zero copy + */ + + + /* + * The following functions should set the low level interface to up or down state + */ + virtual void up() = 0; + virtual void down() = 0; + + // TODO maybe we can manage mac address in the interface + virtual uint8_t* getMacAddress() = 0; + // TODO define callback functions for generic functionalities a network driver has to cope with, like link_up event +protected: + std::function consume_cbk; // TODO move in callbacks + + std::function tx_frame_cbk; + std::function link_up_cbk; + std::function link_down_cbk; +}; \ No newline at end of file diff --git a/libraries/NetworkAPI/src/interface.h b/libraries/NetworkAPI/src/interface.h new file mode 100644 index 00000000..7b9637ef --- /dev/null +++ b/libraries/NetworkAPI/src/interface.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file From 30725adc180fa44d5806c34d2e345bcbede604a8 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 11:08:21 +0100 Subject: [PATCH 03/79] reimplementing the tcp client with the aim of solving issues the issue solved is tcp window were missing and that was due to: - ACK were sent as soonas packets were received and not when they were consumed by the application layer - pbufs where not cleared correctly and following lwip indications --- libraries/lwIpWrapper/src/lwipClient.cpp | 511 +++++++++++++++-------- libraries/lwIpWrapper/src/lwipClient.h | 87 ++-- 2 files changed, 396 insertions(+), 202 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 745f4d50..c22237e2 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -6,36 +6,41 @@ extern "C" { #include "lwipClient.h" -/* -------------------------------------------------------------------------- */ +// FIXME understand hos to syncronize the interrupt thread and "userspace" +// TODO look into tcp_bind_netif for Ethernet and WiFiClient classes +// TODO generalize the functions for extracting and inserting data into pbufs, they may be reused in UDP +// TODO look into application polling: +// When a connection is idle (i.e., no data is either transmitted or received), lwIP will repeatedly poll the application by calling a specified callback function. This can be used either as a watchdog timer for killing connections that have stayed idle for too long, or as a method of waiting for memory to become available. For instance, if a call to tcp_write() has failed because memory wasn't available, the application may use the polling functionality to call tcp_write() again when the connection has been idle for a while. + + +// Forward declarations +err_t _lwip_tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err); +err_t _lwip_tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err); +static err_t _lwip_tcp_sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len); +void _lwip_tcp_err_callback(void *arg, err_t err); + lwipClient::lwipClient() - : _tcp_client(NULL) -{ + : pcb(NULL) { } -/* -------------------------------------------------------------------------- */ /* Deprecated constructor. Keeps compatibility with W5100 architecture sketches but sock is ignored. */ -/* -------------------------------------------------------------------------- */ lwipClient::lwipClient(uint8_t sock) - : _tcp_client(NULL) -{ + : pcb(NULL) { } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -lwipClient::lwipClient(struct tcp_struct* tcpClient) -{ - _tcp_client = tcpClient; +lwipClient::lwipClient(struct tcp_pcb* pcb) +: pcb(pcb) { } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -int lwipClient::connect(const char* host, uint16_t port) -{ - /* -------------------------------------------------------------------------- */ +lwipClient::~lwipClient() { + this->stop(); +} + +int lwipClient::connect(const char* host, uint16_t port) { IPAddress remote_addr; - int ret = CLwipIf::getInstance().getHostByName(host, remote_addr); + int ret = CLwipIf::getInstance().getHostByName(host, remote_addr); // TODO test this if (ret == 1) { return connect(remote_addr, port); } else { @@ -43,222 +48,388 @@ int lwipClient::connect(const char* host, uint16_t port) } } -/* -------------------------------------------------------------------------- */ -int lwipClient::connect(IPAddress ip, uint16_t port) -{ - /* -------------------------------------------------------------------------- */ - if (_tcp_client == NULL) { - /* Allocates memory for client */ - _tcp_client = (struct tcp_struct*)mem_malloc(sizeof(struct tcp_struct)); +int lwipClient::connect(IPAddress ip, uint16_t port) { + err_t err = ERR_OK; + this->pcb = tcp_new(); - if (_tcp_client == NULL) { - return 0; - } + if(this->pcb == nullptr) { + // return ; // TODO find the proper error code + return err; } - /* Creates a new TCP protocol control block */ - _tcp_client->pcb = tcp_new(); + tcp_err(this->pcb, _lwip_tcp_err_callback); // FIXME make this a user callback? + if(err != ERR_OK) { + return err; + } - if (_tcp_client->pcb == NULL) { - return 0; + this->state = TCP_NONE; + + tcp_arg(this->pcb, this); + + this->_ip = fromArduinoIP(ip); + + // FIXME this doesn't include timeout of connection, does lwip have it by default? + err = tcp_connect( + this->pcb, &this->_ip, port, // FIXME check if _ip gets copied + _lwip_tcp_connected_callback // FIXME we need to define a static private function + ); + return err; +} + +err_t _lwip_tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err) { + if(arg == NULL) { + // Setup was not performed correctly and the arg was not setup properly + // _lwip_tcp_connection_close(tpcb, tcp_arg); + // this->stop();// FIXME this doesn't exist + + return ERR_ARG; } - _tcp_client->data.p = NULL; - _tcp_client->data.available = 0; - _tcp_client->state = TCP_NONE; + lwipClient* client = (lwipClient*)arg; - uint32_t startTime = millis(); - ip_addr_t ipaddr; - tcp_arg(_tcp_client->pcb, _tcp_client); - if (ERR_OK != tcp_connect(_tcp_client->pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port, &tcp_connected_callback)) { - stop(); - return 0; + client->connected_callback(tpcb, err); +} + +err_t lwipClient::connected_callback(struct tcp_pcb* tpcb, err_t err) { + if(err != ERR_OK) { + // lwip_tcp_connection_close(tpcb, tcp_arg); + this->stop(); + + return err; } - startTime = millis(); - while (_tcp_client->state == TCP_NONE) { - CLwipIf::getInstance().lwip_task(); - if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= _timeout)) { - stop(); - return 0; - } + if(tcp_arg == NULL) { + // Setup was not performed correctly and the arg was not setup properly + // lwip_tcp_connection_close(tpcb, tcp_arg); + this->stop(); + + return ERR_ARG; } - return 1; + this->state = TCP_CONNECTED; + + /* initialize LwIP tcp_recv callback function */ + tcp_recv(tpcb, _lwip_tcp_recv_callback); + + /* initialize LwIP tcp_sent callback function */ + tcp_sent(tpcb, _lwip_tcp_sent_callback); // FIXME do we actually need it? + + /* initialize LwIP tcp_err callback function */ + // tcp_err(tpcb, lwip_tcp_err_callback); // initialized before, because we may get error during connection + + // TODO understand if this could be helpful + // tcp_poll(tpcb, NULL, 0); + + return err; } -/* -------------------------------------------------------------------------- */ -size_t lwipClient::write(uint8_t b) -{ - /* -------------------------------------------------------------------------- */ - return write(&b, 1); +static err_t _lwip_tcp_sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len) { + if(arg == NULL) { + // Setup was not performed correctly and the arg was not setup properly + // _lwip_tcp_connection_close(tpcb, tcp_arg); + // this->stop(); // FIXME this doesn't exist + + return ERR_ARG; + } + + lwipClient* client = (lwipClient*)arg; } -/* -------------------------------------------------------------------------- */ -size_t lwipClient::write(const uint8_t* buf, size_t size) -{ - /* -------------------------------------------------------------------------- */ - if ((_tcp_client == NULL) || (_tcp_client->pcb == NULL) || (buf == NULL) || (size == 0)) { - return 0; +// callback function that should be called when data has successfully been received (i.e., acknowledged) +// by the remote host. The len argument passed to the callback function gives the amount bytes that +// was acknowledged by the last acknowledgment. +void _lwip_tcp_err_callback(void *arg, err_t err) { + if(arg == NULL) { + // Setup was not performed correctly and the arg was not setup properly + // _lwip_tcp_connection_close(tpcb, tcp_arg); + // this->stop(); // FIXME this doesn't exist + + // return ERR_ARG; + return; } - /* If client not connected or accepted, it can't write because connection is - not ready */ - if ((_tcp_client->state != TCP_ACCEPTED) && (_tcp_client->state != TCP_CONNECTED)) { - return 0; + lwipClient* client = (lwipClient*)arg; + // TODO add a callback for tcp errors in lwipClient +} + +err_t _lwip_tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err) { + if(arg == NULL) { + // Setup was not performed correctly and the arg was not setup properly + // _lwip_tcp_connection_close(tpcb, tcp_arg); + // this->stop(); // FIXME this doesn't exist + + return ERR_ARG; } - size_t max_send_size, bytes_to_send; - size_t bytes_sent = 0; - size_t bytes_left = size; - err_t res; + lwipClient* client = (lwipClient*)arg; - do { - max_send_size = tcp_sndbuf(_tcp_client->pcb); - bytes_to_send = bytes_left > max_send_size ? max_send_size : bytes_left; - - if (bytes_to_send > 0) { - res = tcp_write(_tcp_client->pcb, &buf[bytes_sent], bytes_to_send, TCP_WRITE_FLAG_COPY); - - if (res == ERR_OK) { - bytes_sent += bytes_to_send; - bytes_left = size - bytes_sent; - } else if (res != ERR_MEM) { - // other error, cannot continue - return 0; - } - } + client->recv_callback(tpcb, p, err); +} + +err_t lwipClient::recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err) { + err_t ret_err = ERR_OK; + + // FIXME this checks should be done on every callback + if(err != ERR_OK) { + this->stop(); + return err; + } - // Force to send data right now! - if (ERR_OK != tcp_output(_tcp_client->pcb)) { - return 0; + if (p == NULL) { + // Remote host has closed the connection -> close from our side + this->stop(); + + return ERR_OK; + } + arduino::lock(); + if(this->state == TCP_CONNECTED) { + if (this->pbuf_head == nullptr) { + // no need to increment the references of the pbuf, + // since it is already 1 and lwip shifts the control to this code + this->pbuf_head = p; + } else { + // no need to increment the references of p, since it is already 1 and the only reference is this->pbuf_head->next + pbuf_cat(this->pbuf_head, p); } - CLwipIf::getInstance().lwip_task(); - } while (bytes_sent != size); + ret_err = ERR_OK; + } + arduino::unlock(); - return size; + return ret_err; } -/* -------------------------------------------------------------------------- */ -int lwipClient::available() -{ - /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().lwip_task(); - if (_tcp_client != NULL) { - return _tcp_client->data.available; - } - return 0; +size_t lwipClient::write(uint8_t b) { + return write(&b, 1); } -/* -------------------------------------------------------------------------- */ -int lwipClient::read() -{ - /* -------------------------------------------------------------------------- */ - uint8_t b; - if ((_tcp_client != NULL) && (_tcp_client->data.p != NULL)) { - __disable_irq(); - pbuffer_get_data(&(_tcp_client->data), &b, 1); - __enable_irq(); - return b; - } - // No data available - return -1; +size_t lwipClient::write(const uint8_t* buf, size_t size) { + arduino::lock(); + + uint8_t* buffer_cursor = (uint8_t*)buffer; + uint8_t bytes_to_send = 0; + + do { + bytes_to_send = min(size - (buffer - buffer_cursor), tcp_sndbuf(this->pcb)); + + /* + * TODO: Look into the following flags, especially for write of 1 byte + * TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent + */ + err_t res = tcp_write(this->pcb, buffer_cursor, bytes_to_send, TCP_WRITE_FLAG_COPY); + + if(res == ERR_OK) { + buffer_cursor += bytes_to_send; + } else if(res == ERR_MEM) { + // FIXME handle this: we get into this case only if the sent data cannot be put in the send queue + } + + // TODO understand if the tcp_write will send data if the buffer is not full + // force send only if we filled the send buffer + // if (ERR_OK != tcp_output(this->pcb)) { + // // return 0; + // break; + // } + } while(buffer_cursor < buffer + size); + arduino::unlock(); + + return buffer - buffer_cursor; +} + +int lwipClient::read() { + uint8_t c = 0; + + int res = read(&c, 1); + return res == 1 ? c : res; } -/* -------------------------------------------------------------------------- */ -int lwipClient::read(uint8_t* buf, size_t size) -{ - /* -------------------------------------------------------------------------- */ - if ((_tcp_client != NULL) && (_tcp_client->data.p != NULL)) { - __disable_irq(); - int rv = pbuffer_get_data(&(_tcp_client->data), buf, size); - __enable_irq(); - return rv; +int lwipClient::read(uint8_t* buf, size_t size) { + if(buffer_size==0 || buffer==nullptr || this->pbuf_head==nullptr) { + return 0; // TODO extend checks } - return -1; + // copy data from the lwip buffer to the app provided buffer + // TODO look into pbuf_get_contiguous(this->pbuf_head, buffer_cursor, len); + // pbuf_get_contiguous: returns the pointer to the payload if buffer_size <= pbuf.len + // otherwise copies data in the user provided buffer. This can be used in a callback paradigm, + // in order to avoid memcpy data + + /* + * a chain of pbuf is not granted to have a size multiple of buffer_size length + * meaning that across different calls of this function a pbuf could be partially copied + * we need to account that + */ + arduino::lock(); + uint16_t copied = pbuf_copy_partial(this->pbuf_head, buffer, buffer_size, this->pbuf_offset); + + this->free_pbuf_chain(copied); + // __enable_irq(); + arduino::unlock(); + + return copied; } -/* -------------------------------------------------------------------------- */ -int lwipClient::peek() -{ - /* -------------------------------------------------------------------------- */ +int lwipClient::peek() { uint8_t b; // Unlike recv, peek doesn't check to see if there's any data available, so we must if (!available()) { return -1; } - __disable_irq(); - b = pbuf_get_at(_tcp_client->data.p, 0); - __enable_irq(); + + arduino::lock(); + b = pbuf_get_at(this->pbuf_head, 0); // TODO test this + arduino::unlock(); + return b; } -/* -------------------------------------------------------------------------- */ -void lwipClient::flush() -{ - /* -------------------------------------------------------------------------- */ - if ((_tcp_client == NULL) || (_tcp_client->pcb == NULL)) { +void lwipClient::flush() { + if ((this->pcb == NULL)) { return; } - tcp_output(_tcp_client->pcb); - CLwipIf::getInstance().lwip_task(); + tcp_output(this->pcb); } -/* -------------------------------------------------------------------------- */ -void lwipClient::stop() -{ - /* -------------------------------------------------------------------------- */ - if (_tcp_client == NULL) { - return; - } +void lwipClient::stop() { + tcp_recv(this->pcb, nullptr); + tcp_sent(this->pcb, nullptr); + tcp_poll(this->pcb, nullptr, 0); + tcp_err(this->pcb, nullptr); + tcp_accept(this->pcb, nullptr); - // close tcp connection if not closed yet - if (status() != TCP_CLOSING) { - tcp_connection_close(_tcp_client->pcb, _tcp_client); + if(this->pcb != nullptr) { + err_t err = tcp_close(this->pcb); + this->state = TCP_CLOSING; + + this->pcb = nullptr; + + // FIXME if err != ERR_OK retry, there may be memory issues, retry? } + + // reset all the other variables in this class + + // if(tcp->p != nullptr) { + // pbuf_free(tcp->p); // FIXME it happens that a pbuf, with ref == 0 is added for some reason + // } } -/* -------------------------------------------------------------------------- */ -uint8_t lwipClient::connected() -{ - /* -------------------------------------------------------------------------- */ - uint8_t s = status(); - return ((available() && (s == TCP_CLOSING)) || (s == TCP_CONNECTED) || (s == TCP_ACCEPTED)); +uint8_t lwipClient::connected() { + return this->state != TCP_NONE; //TODO } -/* -------------------------------------------------------------------------- */ -uint8_t lwipClient::status() -{ - if (_tcp_client == NULL) { +uint8_t lwipClient::status() { + if (this == NULL) { return TCP_NONE; } - return _tcp_client->state; + return this->state; } // the next function allows us to use the client returned by // EthernetServer::available() as the condition in an if-statement. -/* -------------------------------------------------------------------------- */ -lwipClient::operator bool() -{ - /* -------------------------------------------------------------------------- */ - return (_tcp_client != nullptr); +lwipClient::operator bool() { + return (this->pcb != nullptr); } -/* -------------------------------------------------------------------------- */ -bool lwipClient::operator==(const lwipClient& rhs) -{ - /* -------------------------------------------------------------------------- */ - return _tcp_client == rhs._tcp_client && _tcp_client->pcb == rhs._tcp_client->pcb; +bool lwipClient::operator==(const lwipClient& rhs) { + // return pcb == rhs.this && this->pcb == rhs.this->pcb; } /* This function is not a function defined by Arduino. This is a function specific to the W5100 architecture. To keep the compatibility we leave it and returns always 0. */ -/* -------------------------------------------------------------------------- */ -uint8_t lwipClient::getSocketNumber() -{ - /* -------------------------------------------------------------------------- */ +uint8_t lwipClient::getSocketNumber() { return 0; } + +// This function is useful for protocol that provide sequence delimiter, like http, +// this allows the user to avoid using temporary buffers +size_t lwipClient::read_until_token( + const uint8_t* buffer, uint16_t buffer_size, char* token, bool &found) { + if(buffer_size==0 || buffer==nullptr || this->pbuf_head==nullptr) { + return 0; // TODO extend checks + } + arduino::lock(); + // TODO check that the buffer size is less than the token len + + uint16_t offset=this->pbuf_offset; + /* iterate over pbufs until: + * - the first occurrence of token + * - the provided buffer is full + * - the available pbufs have been consumed + */ + size_t tkn_len = strlen(token); + + // FIXME if we have already found the token we hare wasting time to check the entire buffer again + uint16_t position = pbuf_memfind(this->pbuf_head, token, tkn_len, this->pbuf_offset); // TODO check efficiency of this function + uint16_t buf_copy_len = buffer_size; + + // TODO triple check the indices of these conditions + if(position != 0xffff && position + tkn_len <= buffer_size) { // TODO consider how to handle the case that the chain is long 0xffff + // We found the token and it fits the user provided buffer + buf_copy_len = position + tkn_len; + found = true; + } else if(position != 0xffff && position < buffer_size && position + tkn_len > buffer_size) { + // if the token is found and fits partially with the user provided buffer + buf_copy_len = position - 1; // copy without consuming the token + found = false; + } else { + /* + * we cover 2 cases here: + * - we didn't find the token + * - we found the token, but it doesn't fit the user provided buffer + */ + found = false; + } + + uint16_t copied = pbuf_copy_partial(this->pbuf_head, (uint8_t*)buffer, buf_copy_len, this->pbuf_offset); + + this->free_pbuf_chain(copied); + arduino::unlock(); + + return copied; +} + +void lwipClient::free_pbuf_chain(uint16_t copied) { + arduino::lock(); + /* + * free pbufs that have been copied, if copied == 0 we have an error + * free the buffer chain starting from the head up to the last entire pbuf ingested + * taking into account the previously not entirely consumed pbuf + */ + uint32_t tobefreed = 0; + copied += this->pbuf_offset; + + // in order to clean up the chain we need to find the pbuf in the last pbuf in the chain + // that got completely consumed by the application, dechain it from it successor and delete the chain before it + + struct pbuf *head = this->pbuf_head, *last=head, *prev=nullptr; // FIXME little optimization prev can be substituted by last->next + + while(last!=nullptr && last->len + tobefreed <= copied) { + tobefreed += last->len; + prev = last; + last = last->next; + } + + // dechain if we are not at the end of the chain (last == nullptr) + // and if we haven't copied entirely the first pbuf (prev == nullptr) (head == last) + // if we reached the end of the chain set the this pbuf pointer to nullptr + if(prev != nullptr && last != nullptr) { + prev->next = nullptr; + this->pbuf_head = last; + } if(last == nullptr) { + this->pbuf_head = nullptr; + } + + // the chain that is referenced by head is detached by the one referenced by this->pbuf_head + // free the chain if we haven't copied entirely the first pbuf (prev == nullptr) + if(this->pbuf_head != head) { + uint8_t refs = pbuf_free(head); + } + + this->pbuf_offset = copied - tobefreed; // This offset should be referenced to the first pbuf in queue + + // acknowledge the received data + tcp_recved(this->pcb, copied); + arduino::unlock(); +} diff --git a/libraries/lwIpWrapper/src/lwipClient.h b/libraries/lwIpWrapper/src/lwipClient.h index 511b3c7f..b087122f 100644 --- a/libraries/lwIpWrapper/src/lwipClient.h +++ b/libraries/lwIpWrapper/src/lwipClient.h @@ -1,63 +1,68 @@ -#ifndef ARDUINO_LWIP_CLIENT_H -#define ARDUINO_LWIP_CLIENT_H - -#include "Arduino.h" -#include "CNetIf.h" -#include "Client.h" -#include "IPAddress.h" -#include "Print.h" -#include "lwipMem.h" -#include "lwipTcp.h" -#include "lwipTypes.h" +#pragma once +#include +#include +#include +#include class lwipClient : public Client { public: lwipClient(); lwipClient(uint8_t sock); - lwipClient(struct tcp_struct* tcpClient); + lwipClient(struct tcp_struct* tcpClient); // FIXME this should be a private constructor, friend of Server - uint8_t status(); + // disable copy constructor + LWIPTCPClient(const LWIPTCPClient&) = delete; + void operator=(const LWIPTCPClient&) = delete; + + // keep move constructor + LWIPTCPClient(LWIPTCPClient&&); + void operator=(LWIPTCPClient&&); + + virtual ~LWIPTCPClient(); + + virtual uint8_t status(); virtual int connect(IPAddress ip, uint16_t port); virtual int connect(const char* host, uint16_t port); + virtual size_t write(uint8_t); virtual size_t write(const uint8_t* buf, size_t size); - virtual int available(); + + inline virtual int available() { return this->pbuf_head == nullptr ? 0 : this->pbuf_head->tot_len; } + virtual int read(); virtual int read(uint8_t* buf, size_t size); + size_t read_until_token( + const uint8_t* buffer, uint16_t buffer_size, char* token, bool &found); + virtual int peek(); virtual void flush(); virtual void stop(); virtual uint8_t connected(); virtual operator bool(); - virtual bool operator==(const bool value) - { + + virtual bool operator==(const bool value) { return bool() == value; } - virtual bool operator!=(const bool value) - { + virtual bool operator!=(const bool value) { return bool() != value; } - virtual bool operator==(const lwipClient&); - virtual bool operator!=(const lwipClient& rhs) - { + virtual bool operator==(const lwipClient&); // TODO why do we need this comparison operators? + virtual bool operator!=(const lwipClient& rhs) { return !this->operator==(rhs); }; + uint8_t getSocketNumber(); - virtual uint16_t localPort() - { + virtual uint16_t localPort() { return (_tcp_client->pcb->local_port); }; - virtual IPAddress remoteIP() - { + virtual IPAddress remoteIP() { return (IPAddress(_tcp_client->pcb->remote_ip.addr)); }; - virtual uint16_t remotePort() - { + virtual uint16_t remotePort() { return (_tcp_client->pcb->remote_port); }; - void setConnectionTimeout(uint16_t timeout) - { + void setConnectionTimeout(uint16_t timeout) { _timeout = timeout; } @@ -66,8 +71,26 @@ class lwipClient : public Client { using Print::write; private: - struct tcp_struct* _tcp_client; + enum _tcp_state_t: uint8_t { + TCP_NONE = 0, + // TCP_ACCEPTED, + TCP_CONNECTED, + TCP_CLOSING + }; + + // TCP related info of the socket + _tcp_state_t state = TCP_NONE; + struct pbuf* pbuf_head = nullptr; + struct tcp_pcb* pcb = nullptr; + uint16_t pbuf_offset = 0; + uint16_t _timeout = 10000; -}; + ip_addr_t _ip; + + err_t connected_callback(struct tcp_pcb* tpcb, err_t err); + void free_pbuf_chain(uint16_t copied); + err_t recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err); -#endif + friend err_t _lwip_tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err); + friend err_t _lwip_tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err); +}; From a0666afb0f534b283868ee164fd98534d2abea1c Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 11:19:03 +0100 Subject: [PATCH 04/79] cleaning up --- libraries/lwIpWrapper/src/CNetIf.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 0b805d20..59efacf1 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -43,17 +43,6 @@ #define WL_MAC_ADDR_LENGTH 6 -/* DEFAULT ADDRESS FOR ETHERNET CONFIGURATION */ - -#define ETH_IFNAME0 'e' -#define ETH_IFNAME1 't' - -#define WST_IFNAME0 'w' -#define WST_IFNAME1 'f' - -#define WSA_IFNAME0 'w' -#define WSA_IFNAME1 'a' - typedef enum { WL_NO_SHIELD = 255, WL_NO_MODULE = WL_NO_SHIELD, @@ -94,11 +83,6 @@ typedef enum { #define MAX_DHCP_TRIES 4 #define TIMEOUT_DNS_REQUEST 10000U -class CNetIf; - -using NetIfRxCb_f = int (*)(CNetIf*); -using LwipInit_f = err_t (*)(struct netif* netif); -using LwipInput_f = err_t (*)(struct pbuf* p, struct netif* inp); #define DHCP_CHECK_NONE (0) #define DHCP_CHECK_RENEW_FAIL (1) From 4c0123f92641efad266d9b4cfffc0fdf55f3fee0 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 11:19:20 +0100 Subject: [PATCH 05/79] redefinition of network Interface classes --- libraries/lwIpWrapper/src/CNetIf.h | 315 +++++++++++------------------ 1 file changed, 120 insertions(+), 195 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 59efacf1..c3dd913d 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -95,77 +95,66 @@ typedef enum { #define TRUNCATED -3 #define INVALID_RESPONSE -4 -typedef enum { - DHCP_IDLE_STATUS, - DHCP_START_STATUS, - DHCP_WAIT_STATUS, - DHCP_GOT_STATUS, - DHCP_RELEASE_STATUS, - DHCP_STOP_STATUS -} DhcpSt_t; ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr); uint32_t ip_addr_to_u32(ip_addr_t* ipaddr); /* Base class implements DHCP, derived class will switch it on or off */ -/* -------------------------------------------------------------------------- */ class CNetIf { - /* -------------------------------------------------------------------------- */ protected: - int id; struct netif ni; -#if LWIP_NETIF_HOSTNAME - char hostname[MAX_HOSTNAME_DIM]; -#endif - - ip_addr_t ip; - ip_addr_t nm; - ip_addr_t gw; - /* these can be overridden by a config() function called before begin() */ - static IPAddress default_ip; - static IPAddress default_nm; - static IPAddress default_gw; - static IPAddress default_dhcp_server_ip; - - unsigned long dhcp_timeout; - DhcpSt_t dhcp_st; - bool dhcp_started; - volatile bool dhcp_acquired; - uint8_t _dhcp_lease_state; - void dhcp_task(); - void dhcp_reset(); - bool dhcp_request(); - uint8_t dhcp_get_lease_state(); +#ifdef LWIP_DHCP + bool dhcp_acquired; +#endif - IPAddress _dnsServerAddress; + // IPAddress _dnsServerAddress; + // Driver interface pointer + NetworkDriver *driver = nullptr; public: CNetIf(); virtual ~CNetIf(); + /* + * The begin function is called by the user in the sketch to initialize the network interface + * that he is planning on using in the sketch. + */ + virtual void begin( + const IPAddress &ip = INADDR_NONE, + const IPAddress &nm = INADDR_NONE, + const IPAddress &gw = INADDR_NONE); + + /* + * This method performs interface specific tasks (if any) + */ + virtual void task(); + +#ifdef LWIP_DHCP /* -------------- * DHCP functions * -------------- */ - bool DhcpIsStarted() { return dhcp_started; } - void DhcpSetTimeout(unsigned long t); - /* stops DHCP */ - void DhcpStop(); - /* tells DHCP is not used on that interface */ - void DhcpNotUsed(); - /* starts DHCP and tries to acquire addresses, return true if acquired, false otherwise */ - bool DhcpStart(); - /* tells if DHCP has acquired addresses or not */ + // starts DHCP and tries to acquire addresses, return true if request was made successfully (ususally memory issues) + bool dhcpStart(); + // stops DHCP + void dhcpStop(); + // tells DHCP server that the interface uses a statically provided ip address + void dhcpNotUsed(); + // force DHCP renewal, returns false on error (ususally memory issues) + bool dhcpRenew(); + // force DHCP release, usually called before dhcp stop (ususally memory issues) + bool dhcpRelease(); + // tells if DHCP has acquired addresses or not bool isDhcpAcquired(); - int checkLease(); +#endif virtual void setLinkUp(); virtual void setLinkDown(); - bool isLinkUp() { return (bool)netif_is_link_up(&ni); } - /* getters / setters */ - void setId(int _id) { id = _id; } - int getId() { return id; } + virtual void up(); + virtual void down(); + + bool isLinkUp() { return (bool)netif_is_link_up(&ni); } struct netif* getNi() { return ∋ } @@ -179,22 +168,8 @@ class CNetIf { memcpy(hostname, name, strlen(name) < MAX_HOSTNAME_DIM ? strlen(name) : MAX_HOSTNAME_DIM); } - /* add */ - virtual void begin(IPAddress _ip, - IPAddress _gw, - IPAddress _nm) - = 0; - virtual void task() = 0; virtual int getMacAddress(uint8_t* mac) = 0; - - /* default dummy implementation because ethernet does not have that */ - virtual const char* getSSID() { return nullptr; } - virtual uint8_t* getBSSID(uint8_t* bssid) { return nullptr; } - virtual int32_t getRSSI() { return 0; } - virtual uint8_t getEncryptionType() { return 0; } - - friend class CWifi; }; /* -------------------------------------------------------------------------- */ @@ -204,62 +179,83 @@ class CEth : public CNetIf { /* * this function is used to initialize the netif structure of lwip */ - static err_t init(struct netif* ni); + static err_t init(struct netif* ni) override; /* * This function is passed to lwip and used to send a buffer to the driver in order to transmit it */ - static err_t output(struct netif* ni, struct pbuf* p); + static err_t output(struct netif* ni, struct pbuf* p) override; + static const char eth_ifname_prefix = 'e'; + static uint8_t eth_id; public: CEth(); virtual ~CEth(); - virtual void begin(IPAddress _ip, - IPAddress _gw, - IPAddress _nm) override; + virtual void begin( + const IPAddress &ip = INADDR_NONE, + const IPAddress &nm = INADDR_NONE, + const IPAddress &gw = INADDR_NONE) override; + virtual void task() override; - virtual int getMacAddress(uint8_t* mac) - { - UNUSED(mac); + virtual int getMacAddress(uint8_t* mac) override { + UNUSED(mac); // FIXME not implemented return 1; } - virtual void handleEthRx(); +private: + /* + * This function is passed to the driver class and it is meant to + * take a pointer to a buffer, and pass it to lwip to process it + */ + void consume_callback(uint8_t* buffer, uint32_t len); }; /* -------------------------------------------------------------------------- */ class CWifiStation : public CNetIf { /* -------------------------------------------------------------------------- */ protected: + static const char wifistation_ifname_prefix = 'w'; + static uint8_t wifistation_id; + /* * this function is used to initialize the netif structure of lwip */ - static err_t init(struct netif* ni); + static err_t init(struct netif* ni) override; /* * This function is passed to lwip and used to send a buffer to the driver in order to transmit it */ - static err_t output(struct netif* ni, struct pbuf* p); + static err_t output(struct netif* ni, struct pbuf* p) override; + + WifiApCfg_t access_point_cfg; public: CWifiStation(); virtual ~CWifiStation(); - virtual void begin(IPAddress _ip, - IPAddress _gw, - IPAddress _nm) override; + virtual void begin( + const IPAddress &ip = INADDR_NONE, + const IPAddress &nm = INADDR_NONE, + const IPAddress &gw = INADDR_NONE) override; + + int connectToAP(const char* ssid, const char *passphrase=nullptr); + int disconnectFromAp(); + int scanForAp(); + virtual void task() override; virtual int getMacAddress(uint8_t* mac) override; - virtual const char* getSSID() override; - virtual uint8_t* getBSSID(uint8_t* bssid) override; - virtual int32_t getRSSI() override; - virtual uint8_t getEncryptionType() override; + virtual const char* getSSID(); + virtual uint8_t* getBSSID(uint8_t* bssid); + virtual int32_t getRSSI(); + virtual uint8_t getEncryptionType(); }; /* -------------------------------------------------------------------------- */ class CWifiSoftAp : public CNetIf { /* -------------------------------------------------------------------------- */ protected: + static const char wifistation_ifname_prefix = 'w'; + static uint8_t wifistation_id; /* * this function is used to initialize the netif structure of lwip */ @@ -269,148 +265,77 @@ class CWifiSoftAp : public CNetIf { * This function is passed to lwip and used to send a buffer to the driver in order to transmit it */ static err_t output(struct netif* ni, struct pbuf* p); + + SoftApCfg_t soft_ap_cfg; public: CWifiSoftAp(); virtual ~CWifiSoftAp(); - virtual void begin(IPAddress _ip, - IPAddress _gw, - IPAddress _nm) override; + virtual void begin( + const IPAddress &ip = INADDR_NONE, + const IPAddress &nm = INADDR_NONE, + const IPAddress &gw = INADDR_NONE) override; virtual void task() override; virtual int getMacAddress(uint8_t* mac) override; - virtual const char* getSSID() override; - virtual uint8_t* getBSSID(uint8_t* bssid) override; - virtual int32_t getRSSI() override; - virtual uint8_t getEncryptionType() override; + virtual const char* getSSID(); + virtual uint8_t* getBSSID(uint8_t* bssid); + virtual int32_t getRSSI(); + virtual uint8_t getEncryptionType(); }; -/* -------------------------------------------------------------------------- */ class CLwipIf { - /* -------------------------------------------------------------------------- */ -private: - bool eth_initialized; - - int dns_num; - bool willing_to_start_sync_req; - bool async_requests_ongoing; - - friend CWifiStation; - friend CWifiSoftAp; - static CNetIf* net_ifs[NETWORK_INTERFACES_MAX_NUM]; - static WifiStatus_t wifi_status; - - /* initialize lwIP and timer */ - CLwipIf(); - -/* timer */ -#ifdef LWIP_USE_TIMER - static FspTimer timer; - static void timer_cb(timer_callback_args_t* arg); -#endif - - std::vector access_points; - WifiApCfg_t access_point_cfg; - - SoftApCfg_t soft_ap_cfg; - - static bool wifi_hw_initialized; - static bool connected_to_access_point; - static int initEventCb(CCtrlMsgWrapper* resp); - static bool initWifiHw(bool asStation); - - static bool pending_eth_rx; - - static int disconnectEventcb(CCtrlMsgWrapper* resp); - - static void dns_callback(const char* name, const ip_addr_t* ipaddr, void* callback_arg); - int8_t get_ip_address_from_hostname(const char* hostname, uint32_t* ipaddr); - int inet2aton(const char* aIPAddrString, IPAddress& aResult); - public: - static CLwipIf& getInstance(); CLwipIf(CLwipIf const&) = delete; void operator=(CLwipIf const&) = delete; - ~CLwipIf(); - bool isEthInitialized() { return eth_initialized; } - void startSyncRequest() - { - if (async_requests_ongoing) { - synchronized - { - willing_to_start_sync_req = true; - } - while (willing_to_start_sync_req) { - delay(1); - } - } + static CLwipIf& getInstance() { + //FIXME this doesn't to seem good + static CLwipIf instance; // this is private in case we need to synch the access to the singleton + return instance; } - void restartAsyncRequest() - { - async_requests_ongoing = true; - delay(10); - timer.enable_overflow_irq(); - } + // run polling tasks from all the LWIP Network Interfaces + // this needs to be called in the loop() if we are not running it + // with a timer + void task(); - /* -------------- - * DNS functions - * -------------- */ + // Function that provides a Client of the correct kind given the protocol provided in url + // Client* connect(std::string url); + // void request(std::string url, std::function); - int getHostByName(const char* aHostname, IPAddress& aResult); - void beginDns(IPAddress aDNSServer); - void addDns(IPAddress aDNSServer); - IPAddress getDns(int _num = 0); + // function for setting an iface as default + void setDefaultIface(CNetIf* iface); - /* when you 'get' a network interface, you get a pointer to one of the pointers - held by net_ifs array - if the array element then an attempt to set up the network interface is made - this function actually calls the private function setUp... and that ones - call the private _get */ + // functions that handle DNS resolution + // DNS servers are also set by dhcp +#if LWIP_DNS + // add a dns server, priority set to 0 means it is the first being queryed, -1 means the last + uint8_t addDnsServer(const IPAddress& aDNSServer, int8_t priority=-1); + void clearDnsServers(); - CNetIf* get(NetIfType_t type, - IPAddress _ip = INADDR_NONE, - IPAddress _gw = INADDR_NONE, - IPAddress _nm = INADDR_NONE); - - static void ethLinkUp(); - static void ethLinkDown(); - - /* this function set the mac address of the corresponding interface to mac - and set this value for lwip */ - bool setMacAddress(NetIfType_t type, uint8_t* mac = nullptr); - int getMacAddress(NetIfType_t type, uint8_t* mac); + // DNS resolution works with a callback if the resolution doesn't return immediately + int getHostByName(const char* aHostname, IPAddress& aResult, bool execute_task=false); // blocking call + int getHostByName(const char* aHostname, std::function cbk); // callback version +#endif +private: + CLwipIf(); - int scanForAp(); - int getApNum(); - const char* getSSID(uint8_t i); - int32_t getRSSI(uint8_t i); - uint8_t getEncrType(uint8_t i); - uint8_t* getBSSID(uint8_t i, uint8_t* bssid); - uint8_t getChannel(uint8_t i); - int connectToAp(const char* ssid, const char* pwd); - int disconnectFromAp(); - const char* getSSID(); - uint8_t* getBSSID(uint8_t* bssid); - uint32_t getRSSI(); - uint8_t getEncrType(); + // TODO define a Timer for calling tasks - WifiStatus_t getWifiStatus() { return wifi_status; } + std::vector ifaces; - int startSoftAp(const char* ssid, const char* passphrase, uint8_t channel); - int setLowPowerMode(); - int resetLowPowerMode(); + virtual void add_iface(CNetIf* iface); + // virtual void del_iface(CNetIf* iface); - const char* getSSID(NetIfType_t type); - uint8_t* getBSSID(NetIfType_t type, uint8_t* bssid); - int32_t getRSSI(NetIfType_t type); - uint8_t getEncryptionType(NetIfType_t type); + // lwip stores the netif in a linked list called: netif_list - int setWifiMode(WifiMode_t mode); + friend class CNetIf; - void lwip_task(); +#ifdef NETWORKSTACK_USE_TIMER + FspTimer timer; +#endif }; #endif From 2637cdfd5dd5cf41d8a2301a331ff601e06db178 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 15:48:52 +0100 Subject: [PATCH 06/79] restructuring CLwipIf singleton class --- libraries/lwIpWrapper/src/CNetIf.cpp | 455 +++++++++------------------ 1 file changed, 154 insertions(+), 301 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 53f01dd7..8d7555dc 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -1,32 +1,57 @@ #include "CNetIf.h" #include -IPAddress CNetIf::default_ip("192.168.0.10"); -IPAddress CNetIf::default_nm("255.255.255.0"); -IPAddress CNetIf::default_gw("192.168.0.1"); -IPAddress CNetIf::default_dhcp_server_ip("192.168.4.1"); +// TODO make better documentation on how this works +// TODO hostname should be defined at network stack level and shared among ifaces +// TODO buffer management (allocation/deallocation/trim/etc.) should be properly handled by a wrapper class and be transparent wrt the user +// TODO the device could be moving and as a consequence it may be nice to rescan APs to get one with the best rssi +// TODO implement setLowPowerMode and resetLowPowerMode in WIFI driver +// TODO implement stop softAP and include it in the destructor of the class +// TODO split netif definition in different files +// TODO implement WIFINetworkDriver that is then being used by both Wifi station and softAP. This will allow to use both at the same time + +err_t _netif_init(struct netif* ni); +err_t _netif_output(struct netif* ni, struct pbuf* p); -CNetIf* CLwipIf::net_ifs[] = { nullptr }; -bool CLwipIf::wifi_hw_initialized = false; -bool CLwipIf::connected_to_access_point = false; -WifiStatus_t CLwipIf::wifi_status = WL_IDLE_STATUS; -bool CLwipIf::pending_eth_rx = false; +#if LWIP_DNS +static void _getHostByNameCBK(const char *name, const ip_addr_t *ipaddr, void *callback_arg); +#endif // LWIP_DNS -FspTimer CLwipIf::timer; +// Custom Pbuf definition used to handle RX zero copy +// TODO Move this in a separate file (understand if it is required) +typedef struct zerocopy_pbuf { + struct pbuf_custom p; + uint8_t* buffer; + uint32_t size; + void(*buffer_free)(void*); +} zerocopy_pbuf_t; -ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr) -{ - IP_ADDR4(ipaddr, ipu8[0], ipu8[1], ipu8[2], ipu8[3]); - return ipaddr; +static void zerocopy_pbuf_mem_free(struct pbuf *p) { + // SYS_ARCH_DECL_PROTECT(zerocopy_pbuf_free); + zerocopy_pbuf_t* zcpbuf = (zerocopy_pbuf_t*) p; + + // arduino::lock(); + // SYS_ARCH_PROTECT(zerocopy_pbuf_free); + + // FIXME pbufs may be allocated in a different memory pool, deallocate them accordingly + zcpbuf->buffer_free(zcpbuf->buffer); + zcpbuf->buffer = nullptr; + mem_free(zcpbuf); // TODO understand if pbuf_free deletes the pbuf + // SYS_ARCH_UNPROTECT(zerocopy_pbuf_free); + + // arduino::unlock(); } -uint32_t ip_addr_to_u32(ip_addr_t* ipaddr) -{ - return ip4_addr_get_u32(ipaddr); +static inline zerocopy_pbuf_t* get_zerocopy_pbuf(uint8_t *buffer, uint32_t size, void(*buffer_free)(void*) = mem_free) { + zerocopy_pbuf_t* p = (zerocopy_pbuf_t*)mem_malloc(sizeof(zerocopy_pbuf_t)); + p->buffer = buffer; + p->size = size; + p->p.custom_free_function = zerocopy_pbuf_mem_free; + p->buffer_free = buffer_free; + return p; } -static uint8_t Encr2wl_enc(int enc) -{ +static uint8_t Encr2wl_enc(int enc) { if (enc == WIFI_AUTH_OPEN) { return ENC_TYPE_NONE; } else if (enc == WIFI_AUTH_WEP) { @@ -48,20 +73,13 @@ static uint8_t Encr2wl_enc(int enc) } } -/* -------------------------------------------------------------------------- */ -CLwipIf::CLwipIf() - : eth_initialized(false) - , dns_num(-1) - , willing_to_start_sync_req(false) - , async_requests_ongoing(true) -{ - /* -------------------------------------------------------------------------- */ +CLwipIf::CLwipIf() { + /* Initialize lwIP stack, singletone implementation guarantees that lwip is initialized just once */ lwip_init(); -/* START THE TIMER FOR LWIP tasks - #CORE_DEPENDENT_STUFF */ -#ifdef LWIP_USE_TIMER +#ifdef NETWORKSTACK_USE_TIMER uint8_t type = 8; int8_t ch = FspTimer::get_available_timer(type); @@ -84,327 +102,162 @@ CLwipIf::CLwipIf() * Since this is a constrained environment we could accept performance loss and * delegate lwip to handle lost packets. */ - timer.begin(TIMER_MODE_PERIODIC, type, ch, 100.0, 50.0, timer_cb); - timer.setup_overflow_irq(); - timer.open(); - timer.start(); + timer.begin(TIMER_MODE_PERIODIC, type, ch, 100.0, 0, timer_cb, this); // TODO make the user decide how to handle these parameters #endif } -/* -------------------------------------------------------------------------- */ -void CLwipIf::lwip_task() -{ - /* -------------------------------------------------------------------------- */ - if (CLwipIf::wifi_hw_initialized) - CEspControl::getInstance().communicateWithEsp(); - - if (net_ifs[NI_ETHERNET] != nullptr) { - net_ifs[NI_ETHERNET]->task(); +void CLwipIf::task() { + for(CNetIf* iface: this->ifaces) { // FIXME is this affecting performances? + iface->task(); } - if (net_ifs[NI_WIFI_STATION] != nullptr) { - net_ifs[NI_WIFI_STATION]->task(); - } - - if (net_ifs[NI_WIFI_SOFTAP] != nullptr) { - net_ifs[NI_WIFI_SOFTAP]->task(); - } - - /* Handle LwIP timeouts */ + arduino::lock(); sys_check_timeouts(); - - if (willing_to_start_sync_req) { - timer.disable_overflow_irq(); - willing_to_start_sync_req = false; - async_requests_ongoing = false; - } + arduino::unlock(); } -/* -------------------------------------------------------------------------- */ -/* GET INSTANCE SINGLETONE FUNCTION */ -/* -------------------------------------------------------------------------- */ -CLwipIf& CLwipIf::getInstance() -{ - /* -------------------------------------------------------------------------- */ - static CLwipIf instance; - return instance; -} +void CLwipIf::setDefaultIface(CNetif* iface) { + // TODO check if the iface is in the vector -/* -------------------------------------------------------------------------- */ -CLwipIf::~CLwipIf() -{ - /* -------------------------------------------------------------------------- */ - for (int i = 0; i < NETWORK_INTERFACES_MAX_NUM; i++) { - if (net_ifs[i] != nullptr) { - delete net_ifs[i]; - net_ifs[i] = nullptr; - } - } + netif_set_default(&iface->ni); } -/* -------------------------------------------------------------------------- */ -int CLwipIf::disconnectEventcb(CCtrlMsgWrapper *resp) { - (void)resp; - if(CLwipIf::connected_to_access_point) { - wifi_status = WL_DISCONNECTED; - if(net_ifs[NI_WIFI_STATION] != nullptr) { - net_ifs[NI_WIFI_STATION]->setLinkDown(); - } +void CLwipIf::add_iface(CNetif* iface) { + // if it is the first interface set it as the default route + if(this->ifaces.empty()) { + netif_set_default(&iface->ni); // TODO let the user decide which is the default one + +#ifdef NETWORKSTACK_USE_TIMER + timer.setup_overflow_irq(); + timer.open(); + timer.start(); +#endif } - return ESP_CONTROL_OK; -} + // add the interface if not already present in the vector + this->ifaces.push_back(iface); +} -/* -------------------------------------------------------------------------- */ -int CLwipIf::initEventCb(CCtrlMsgWrapper *resp) { - (void)resp; - CLwipIf::wifi_hw_initialized = true; - return ESP_CONTROL_OK; +CLwipIf::~CLwipIf() { + // TODO free iface array } -/* -------------------------------------------------------------------------- */ int CLwipIf::setWifiMode(WifiMode_t mode) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().startSyncRequest(); - int rv = CEspControl::getInstance().setWifiMode(mode); - CLwipIf::getInstance().restartAsyncRequest(); - return rv; + // TODO adapt this + // CLwipIf::getInstance().startSyncRequest(); + // int rv = CEspControl::getInstance().setWifiMode(mode); + // CLwipIf::getInstance().restartAsyncRequest(); + // return rv; } -/* -------------------------------------------------------------------------- */ -bool CLwipIf::initWifiHw(bool asStation) -{ - /* -------------------------------------------------------------------------- */ - bool rv = true; - - if (!CLwipIf::wifi_hw_initialized) { - - CEspControl::getInstance().listenForStationDisconnectEvent(CLwipIf::disconnectEventcb); - CEspControl::getInstance().listenForInitEvent(CLwipIf::initEventCb); - if (CEspControl::getInstance().initSpiDriver() == 0) { - wifi_status = WL_NO_SSID_AVAIL; - } +/* *************************************************************************** + * DNS related functions + * ****************************************************************************/ - if (wifi_status == WL_NO_SSID_AVAIL) { - int time_num = 0; - while (time_num < WIFI_INIT_TIMEOUT_MS && !CLwipIf::wifi_hw_initialized) { - CEspControl::getInstance().communicateWithEsp(); - R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS); - time_num++; - } +#if LWIP_DNS - if (asStation) { - int res = CLwipIf::getInstance().setWifiMode(WIFI_MODE_STA); +struct dns_callback { + std::function cbk; +}; - if (res == ESP_CONTROL_OK) { - CLwipIf::getInstance().scanForAp(); - } - } else { - CEspControl::getInstance().setWifiMode(WIFI_MODE_AP); - } - } - } +static void _getHostByNameCBK(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { + dns_callback* cbk = (dns_callback*)callback_arg; - if (wifi_status != WL_SCAN_COMPLETED) { - rv = false; - } + cbk->cbk(toArduinoIP(ipaddr)); - return rv; + delete cbk; } -/* -------------------------------------------------------------------------- */ -/* Sort of factory method, dependig on the requested type it setUp a different - Network interface and returns it to the caller */ -/* -------------------------------------------------------------------------- */ -CNetIf* CLwipIf::get(NetIfType_t type, - IPAddress _ip, - IPAddress _gw, - IPAddress _nm) -{ - /* -------------------------------------------------------------------------- */ - static int id = 0; - CNetIf* rv = nullptr; - bool isStation = true; - bool isEth = false; - - if (type >= 0 && type < NETWORK_INTERFACES_MAX_NUM) { - if (net_ifs[type] == nullptr) { - switch (type) { - case NI_WIFI_STATION: - net_ifs[type] = new CWifiStation(); - isStation = true; - break; +// add a dns server, priority set to 0 means it is the first being queryed, -1 means the last +uint8_t CLwipIf::addDnsServer(const IPAddress& aDNSServer, int8_t priority) { + // TODO test this function with all the possible cases of dns server position + if(priority == -1) { + // lwip has an array for dns servers that can be iterated with dns_getserver(num) + // when a dns server is set to any value, it means it is the last - case NI_WIFI_SOFTAP: - net_ifs[type] = new CWifiSoftAp(); - isStation = false; - break; - - case NI_ETHERNET: - net_ifs[type] = new CEth(); - isEth = true; - break; - default: - break; - } - - if (net_ifs[type] != nullptr) { - if (!isEth) { - CLwipIf::initWifiHw(isStation); - net_ifs[type]->begin(_ip, _gw, _nm); - net_ifs[type]->setId(0); - } else { - eth_init(); - net_ifs[type]->begin(_ip, _gw, _nm); - eth_initialized = true; - } - } - } - rv = net_ifs[type]; + for(priority=0; + priority 0 && rx_frame_buf != nullptr) { - struct pbuf* p=nullptr; - p = pbuf_alloc(PBUF_RAW, rx_frame_dim, PBUF_RAM); - - if (p != NULL) { - /* Copy ethernet frame into pbuf */ - pbuf_take((struct pbuf*)p, (uint8_t*)rx_frame_buf, (uint32_t)rx_frame_dim); - - if (ni.input((struct pbuf*)p, &ni) != ERR_OK) { - pbuf_free((struct pbuf*)p); - } - } - - eth_release_rx_buffer(); + if(priority >= DNS_MAX_SERVERS) { + // unable to add another dns server, because priority is more than the dns server available space + return -1; } - __enable_irq(); -} -/* -------------------------------------------------------------------------- */ -err_t CEth::init(struct netif* _ni) -{ - /* -------------------------------------------------------------------------- */ -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - _ni->hostname = "C33-onEth"; -#endif /* LWIP_NETIF_HOSTNAME */ - - _ni->name[0] = ETH_IFNAME0; - _ni->name[1] = ETH_IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - _ni->output = etharp_output; - _ni->linkoutput = CEth::output; - - /* set MAC hardware address */ - _ni->hwaddr_len = eth_get_mac_address(_ni->hwaddr); + ip_addr_t ip = fromArduinoIP(aDNSServer); - /* maximum transfer unit */ - _ni->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - _ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + dns_setserver(priority, &ip); +} - return ERR_OK; +void CLwipIf::clearDnsServers() { + for(uint8_t i=0; itot_len; + uint8_t res = this->getHostByName(aHostname, [&aResult, &completed](const IPAddress& ip){ + aResult = ip; + completed = true; + }); - // TODO analyze the race conditions that may arise from sharing a non synchronized buffer - uint8_t *tx_buf = eth_get_tx_buffer(&tx_buf_dim); - if (p->tot_len <= tx_buf_dim) { - - uint16_t bytes_actually_copied = pbuf_copy_partial(p, tx_buf, p->tot_len, 0); - - if (bytes_actually_copied > 0 && !eth_output(tx_buf, bytes_actually_copied)) { - errval = ERR_IF; - } - } else { - errval = ERR_MEM; + while(res == 1 && !completed) { // DNS timeouts seems to be handled by lwip, no need to put one here + delay(1); + if(execute_task) { + this->task(); } - } else { - errval = ERR_INPROGRESS; } - return errval; + + return res == 1 ? 0 : res; } -/* -------------------------------------------------------------------------- */ -err_t CWifiStation::output(struct netif* _ni, struct pbuf *p) { -/* -------------------------------------------------------------------------- */ - (void)_ni; - err_t errval = ERR_IF; - uint8_t *buf = new uint8_t[p->tot_len]; - if (buf != nullptr) { - uint16_t bytes_actually_copied = pbuf_copy_partial(p, buf, p->tot_len, 0); - if (bytes_actually_copied > 0) { - int ifn = 0; - if (CLwipIf::net_ifs[NI_WIFI_STATION] != nullptr) { - ifn = CLwipIf::net_ifs[NI_WIFI_STATION]->getId(); - } +// TODO instead of returning int return an enum value +int CLwipIf::getHostByName(const char* aHostname, std::function cbk) { + ip_addr_t addr; // TODO understand if this needs to be in the heap + uint8_t res = 0; -#ifdef DEBUG_OUTPUT_DISABLED - Serial.println("Bytes LWIP wants to send: "); + dns_callback* dns_cbk = new dns_callback; + dns_cbk->cbk = cbk; + err_t err = dns_gethostbyname(aHostname, &addr, _getHostByNameCBK, dns_cbk); - for (int i = 0; i < bytes_actually_copied; i++) { - Serial.print(buf[i], HEX); - Serial.print(" "); - } - Serial.println(); -#endif + switch(err) { + case ERR_OK: + // the address was already present in the local cache + cbk(toArduinoIP(&addr)); - if (CEspControl::getInstance().sendBuffer(ESP_STA_IF, ifn, buf, bytes_actually_copied) == ESP_CONTROL_OK) { - errval = ERR_OK; - } - } - delete[] buf; + delete dns_cbk; + break; + case ERR_INPROGRESS: + // the address is not present in the local cache, return and wait for the address resolution to complete + res = 1; + break; + case ERR_ARG: // there are issues in the arguments passed + default: + delete dns_cbk; + res = -1; } - return errval; + return res; } +#endif + +/* ########################################################################## + * BASE NETWORK INTERFACE CLASS + * ########################################################################## */ /* -------------------------------------------------------------------------- */ err_t CWifiStation::init(struct netif* _ni) From 216e3aab05b7b40e62952cab93316b358a4160f9 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 16:46:57 +0100 Subject: [PATCH 07/79] rewriting CNetif base class --- libraries/lwIpWrapper/src/CNetIf.cpp | 267 +++++++++------------------ 1 file changed, 88 insertions(+), 179 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 8d7555dc..dc1ddd0e 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -259,221 +259,130 @@ int CLwipIf::getHostByName(const char* aHostname, std::functionhostname = "C33-WifiSta"; -#endif /* LWIP_NETIF_HOSTNAME */ - - _ni->name[0] = WST_IFNAME0; - _ni->name[1] = WST_IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - _ni->output = etharp_output; - _ni->linkoutput = CWifiStation::output; + // NETIF_STATS_INIT(this->stats); // TODO create a proper stats interface - /* maximum transfer unit */ - _ni->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - _ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - - /* set MAC hardware address */ - _ni->hwaddr_len = CLwipIf::getInstance().getMacAddress(NI_WIFI_STATION, _ni->hwaddr); - - return ERR_OK; + if(driver != nullptr) { + // driver->stats = this->stats; // TODO + // TODO check that this calls are effective + driver->setLinkDownCallback(std::bind(&CNetIf::linkDownCallback, this)); + driver->setLinkUpCallback(std::bind(&CNetIf::linkUpCallback, this)); + } } -/* -------------------------------------------------------------------------- */ -err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) -{ - /* -------------------------------------------------------------------------- */ - (void)_ni; - err_t errval = ERR_IF; - - uint8_t* buf = new uint8_t[p->tot_len]; +void CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { + ip_addr_t _ip = fromArduinoIP(ip); + ip_addr_t _nm = fromArduinoIP(nm); + ip_addr_t _gw = fromArduinoIP(gw); + + // netif add copies the ip addresses into the netif, no need to store them also in the object + struct netif *_ni = netif_add( + &this->ni, + &_ip, &_nm, &_gw, // ip addresses are being copied and not taken as reference, use a local defined variable + this, + _netif_init, + ethernet_input + ); + if(_ni == nullptr) { + // FIXME error if netif_add, return error + return; + } - if (buf != nullptr) { - uint16_t bytes_actually_copied = pbuf_copy_partial(p, buf, p->tot_len, 0); - if (bytes_actually_copied > 0) { - int ifn = 0; - if (CLwipIf::net_ifs[NI_WIFI_SOFTAP] != nullptr) { - ifn = CLwipIf::net_ifs[NI_WIFI_SOFTAP]->getId(); - } + //TODO add link up and down callback and set the link + netif_set_up(&this->ni); - if (CEspControl::getInstance().sendBuffer(ESP_AP_IF, ifn, buf, bytes_actually_copied) == ESP_CONTROL_OK) { - errval = ERR_OK; - } - } - delete[] buf; +#ifdef LWIP_DHCP + // dhcp is started when begin gets ip == nullptr + if(ip != INADDR_NONE) { + this->dhcpNotUsed(); + } else { + this->dhcpStart(); } +#endif - return errval; + // add the interface to the network stack + CLwipIf::getInstance().add_iface(this); // TODO remove interface when it is needed (??) } -/* -------------------------------------------------------------------------- */ -err_t CWifiSoftAp::init(struct netif* _ni) -{ - /* -------------------------------------------------------------------------- */ -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - _ni->hostname = "C33-WifiSta"; -#endif /* LWIP_NETIF_HOSTNAME */ - - _ni->name[0] = WSA_IFNAME0; - _ni->name[1] = WSA_IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - _ni->output = etharp_output; - _ni->linkoutput = CWifiSoftAp::output; +void CNetif::task() { +#ifdef LWIP_DHCP + // TODO we can add a lazy evaluated timer for this condition if dhcp_supplied_address takes too long + if(!this->dhcp_acquired && dhcp_supplied_address(&this->ni)) { + dhcp_acquired = true; + } - /* maximum transfer unit */ - _ni->mtu = 1500; +#endif + if(driver != nullptr) { + driver->poll(); + } +} - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - _ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - /* set MAC hardware address */ - _ni->hwaddr_len = CLwipIf::getInstance().getMacAddress(NI_WIFI_SOFTAP, _ni->hwaddr); +err_t _netif_init(struct netif* ni) { + CNetif *iface = (CNetif*)ni->state; - return ERR_OK; + return iface->init(ni); // This function call can be a jmp instruction } -/* -------------------------------------------------------------------------- */ -bool CLwipIf::setMacAddress(NetIfType_t type, uint8_t* mac) -{ - /* -------------------------------------------------------------------------- */ +err_t _netif_output(struct netif* ni, struct pbuf* p) { + CNetif *iface = (CNetif*)ni->state; - CLwipIf::getInstance().startSyncRequest(); - WifiMac_t MAC; - CNetUtilities::macArray2macStr(MAC.mac, mac); + return iface->output(ni, p); // This function call can be a jmp instruction +} - if (type == NI_WIFI_STATION) { - MAC.mode = WIFI_MODE_STA; - if (CEspControl::getInstance().setWifiMacAddress(MAC) != ESP_CONTROL_OK) { - return false; - } +void CNetIf::up() { + netif_set_up(&this->ni); +} - } else if (type == NI_WIFI_SOFTAP) { - MAC.mode = WIFI_MODE_AP; - if (CEspControl::getInstance().setWifiMacAddress(MAC) != ESP_CONTROL_OK) { - return false; - } - } else { - eth_set_mac_address(mac); - } +void CNetIf::down() { + netif_set_down(&this->ni); +} - CLwipIf::getInstance().restartAsyncRequest(); - return true; +void CNetIf::linkUpCallback() { + netif_set_link_up(&this->ni); // TODO check that this sets the interface up also } -/* -------------------------------------------------------------------------- */ -int CLwipIf::getMacAddress(NetIfType_t type, uint8_t* mac) -{ - /* -------------------------------------------------------------------------- */ - int rv = 0; - WifiMac_t MAC; +void CNetIf::linkDownCallback() { + netif_set_link_down(&this->ni); // TODO check that this sets the interface down also +} - CLwipIf::getInstance().startSyncRequest(); +/* ########################################################################## + * DHCP related functions + * ########################################################################## */ - if (type == NI_WIFI_STATION) { - MAC.mode = WIFI_MODE_STA; - if (CEspControl::getInstance().getWifiMacAddress(MAC) == ESP_CONTROL_OK) { - CNetUtilities::macStr2macArray(mac, MAC.mac); - rv = MAC_ADDRESS_DIM; - } - } else if (type == NI_WIFI_SOFTAP) { - MAC.mode = WIFI_MODE_AP; - if (CEspControl::getInstance().getWifiMacAddress(MAC) == ESP_CONTROL_OK) { - CNetUtilities::macStr2macArray(mac, MAC.mac); - rv = MAC_ADDRESS_DIM; - } - } else { - eth_get_mac_address(mac); - rv = MAC_ADDRESS_DIM; - } - CLwipIf::getInstance().restartAsyncRequest(); - return rv; -} +#ifdef LWIP_DHCP -/* -------------------------------------------------------------------------- */ -int CLwipIf::scanForAp() -{ - /* -------------------------------------------------------------------------- */ - access_points.clear(); - CLwipIf::getInstance().startSyncRequest(); - int res = CEspControl::getInstance().getAccessPointScanList(access_points); - CLwipIf::getInstance().restartAsyncRequest(); - if (res == ESP_CONTROL_OK) { - wifi_status = WL_SCAN_COMPLETED; - } else { - wifi_status = WL_NO_SSID_AVAIL; - } - return res; +void CNetIf::dhcpNotUsed() { + dhcp_inform(&this->ni); } -/* -------------------------------------------------------------------------- */ -int CLwipIf::getApNum() { return access_points.size(); } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -const char* CLwipIf::getSSID(uint8_t i) -{ - /* -------------------------------------------------------------------------- */ - if (access_points.size() > 0 && i < access_points.size()) { - return (const char*)access_points[i].ssid; +bool CNetIf::isDhcpAcquired() { + if(dhcp_acquired) { + Serial.println(ip_2_ip4(ni.ip_addr).addr, HEX); } - return nullptr; + return dhcp_acquired; } -/* -------------------------------------------------------------------------- */ -int32_t CLwipIf::getRSSI(uint8_t i) -{ - /* -------------------------------------------------------------------------- */ - if (access_points.size() > 0 && i < access_points.size()) { - return (int32_t)access_points[i].rssi; - } - return 0; +bool CNetIf::dhcpStart() { + return dhcp_start(&this->ni) == ERR_OK; } -/* -------------------------------------------------------------------------- */ -uint8_t CLwipIf::getEncrType(uint8_t i) -{ - /* -------------------------------------------------------------------------- */ - if (access_points.size() > 0 && i < access_points.size()) { - return Encr2wl_enc(access_points[i].encryption_mode); - } - return 0; +void CNetIf::dhcpStop() { + this->dhcpRelease(); + dhcp_stop(&this->ni); } - -/* -------------------------------------------------------------------------- */ -uint8_t* CLwipIf::getBSSID(uint8_t i, uint8_t* bssid) -{ - /* -------------------------------------------------------------------------- */ - if (access_points.size() > 0 && i < access_points.size()) { - CNetUtilities::macStr2macArray(bssid, (const char*)access_points[i].bssid); - return bssid; - } - return nullptr; +bool CNetIf::dhcpRelease() { + return dhcp_release(&this->ni) == ERR_OK; } -/* -------------------------------------------------------------------------- */ -uint8_t CLwipIf::getChannel(uint8_t i) -{ - /* -------------------------------------------------------------------------- */ - if (access_points.size() > 0 && i < access_points.size()) { - return (uint8_t)access_points[i].channel; - } - return 0; +bool CNetIf::dhcpRenew() { + return dhcp_renew(&this->ni) == ERR_OK; } /* -------------------------------------------------------------------------- */ int CLwipIf::connectToAp(const char* ssid, const char* pwd) From 28f91995ac6003ecf66e334bea138b55e89138b2 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 28 Dec 2023 16:48:22 +0100 Subject: [PATCH 08/79] rewriting CEth CwifiStation and CSoftAP classes --- libraries/lwIpWrapper/src/CNetIf.cpp | 1243 ++++++++++---------------- 1 file changed, 469 insertions(+), 774 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index dc1ddd0e..86f7413e 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -384,927 +384,622 @@ bool CNetIf::dhcpRelease() { bool CNetIf::dhcpRenew() { return dhcp_renew(&this->ni) == ERR_OK; } -/* -------------------------------------------------------------------------- */ -int CLwipIf::connectToAp(const char* ssid, const char* pwd) -{ - /* -------------------------------------------------------------------------- */ - WifiApCfg_t ap; - int rv = ESP_CONTROL_CTRL_ERROR; - bool found = false; - uint8_t index = 0; - for (uint8_t i = 0; i < access_points.size() && !found; i++) { - if (strcmp(ssid, (const char*)access_points[i].ssid) == 0) { - found = true; - index = i; - } - } - - if (found) { - memset(ap.ssid, 0x00, SSID_LENGTH); - memcpy(ap.ssid, access_points[index].ssid, SSID_LENGTH); - memset(ap.pwd, 0x00, PASSWORD_LENGTH); - if (pwd != nullptr) { - memcpy(ap.pwd, pwd, (strlen(pwd) < PASSWORD_LENGTH) ? strlen(pwd) : PASSWORD_LENGTH); - } - memset(ap.bssid, 0x00, BSSID_LENGTH); - memcpy(ap.bssid, access_points[index].bssid, BSSID_LENGTH); - - CLwipIf::getInstance().startSyncRequest(); - if (CEspControl::getInstance().connectAccessPoint(ap) == ESP_CONTROL_OK) { - CLwipIf::connected_to_access_point = true; - wifi_status = WL_CONNECTED; - CEspControl::getInstance().getAccessPointConfig(access_point_cfg); - rv = ESP_CONTROL_OK; - /* when we get the connection to access point we are sure we are STATION - and we are connected */ - if (CLwipIf::net_ifs[NI_WIFI_STATION] != nullptr) { - CLwipIf::net_ifs[NI_WIFI_STATION]->setLinkUp(); - } - - } - else { - - wifi_status = WL_CONNECT_FAILED; - CLwipIf::connected_to_access_point = false; - } - - CLwipIf::getInstance().restartAsyncRequest(); - } - else { - /* in case SSID was available scan again for access point - (perhaps a wifi hostpoint has been added) */ - CLwipIf::getInstance().scanForAp(); - //Serial.println("SSID not found in the list of available AP"); - } - return rv; -} +#endif -/* -------------------------------------------------------------------------- */ -const char* CLwipIf::getSSID() -{ - /* -------------------------------------------------------------------------- */ - return (const char*)access_point_cfg.ssid; -} +/* ########################################################################## + * ETHERNET NETWORK INTERFACE CLASS + * ########################################################################## */ +uint8_t CEth::eth_id = 0; -/* -------------------------------------------------------------------------- */ -uint8_t* CLwipIf::getBSSID(uint8_t* bssid) -{ - /* -------------------------------------------------------------------------- */ - CNetUtilities::macStr2macArray(bssid, (const char*)access_point_cfg.bssid); - return bssid; +CEth::CEth() { + CNetif::driver = &C33EthernetDriver; // FIXME driver is the pointer to C33 ethernet driver implementation + C33EthernetDriver.stats = &this->stats; } -/* -------------------------------------------------------------------------- */ -uint32_t CLwipIf::getRSSI() -{ - /* -------------------------------------------------------------------------- */ - return (uint32_t)access_point_cfg.rssi; -} +void CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { + // The driver needs a callback to consume the incoming buffer + this->driver->setConsumeCallback( + std::bind(&CEth::consume_callback, + this, std::placeholders:: _1, std::placeholders::_2)); -/* -------------------------------------------------------------------------- */ -uint8_t CLwipIf::getEncrType() -{ - /* -------------------------------------------------------------------------- */ - return Encr2wl_enc(access_point_cfg.encryption_mode); + // Call the begin function on the Parent class to init the interface + CNetif::begin(ip, nm, gw); + netif_set_link_up(&this->ni); // TODO test that moving this here still makes ethernet work } -/* -------------------------------------------------------------------------- */ -int CLwipIf::disconnectFromAp() -{ - /* -------------------------------------------------------------------------- */ - wifi_status = WL_DISCONNECTED; - CLwipIf::getInstance().startSyncRequest(); - int rv = CEspControl::getInstance().disconnectAccessPoint(); - CLwipIf::getInstance().restartAsyncRequest(); - wifi_status = WL_DISCONNECTED; - if (net_ifs[NI_WIFI_STATION] != nullptr) { - net_ifs[NI_WIFI_STATION]->setLinkDown(); - } - return rv; -} -/* -------------------------------------------------------------------------- */ -int CLwipIf::startSoftAp(const char* ssid, const char* passphrase, uint8_t channel) -{ - /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().startSyncRequest(); - SoftApCfg_t cfg; - memset(cfg.ssid, 0x00, SSID_LENGTH); - memcpy(cfg.ssid, ssid, (strlen(ssid) < SSID_LENGTH) ? strlen(ssid) : SSID_LENGTH); - memset(cfg.pwd, 0x00, PASSWORD_LENGTH); - if (passphrase == nullptr) { - memcpy(cfg.pwd, "arduinocc", strlen("arduinocc")); - } else { - memcpy(cfg.pwd, passphrase, strlen(passphrase) < PASSWORD_LENGTH ? strlen(passphrase) : PASSWORD_LENGTH); - } - channel = (channel == 0) ? 1 : channel; - cfg.channel = (channel > MAX_CHNL_NO) ? MAX_CHNL_NO : channel; - cfg.max_connections = MAX_SOFAT_CONNECTION_DEF; - cfg.encryption_mode = WIFI_AUTH_WPA_WPA2_PSK; - cfg.bandwidth = WIFI_BW_HT40; - cfg.ssid_hidden = false; +err_t CEth::init(struct netif* ni) { + // Setting up netif +#if LWIP_NETIF_HOSTNAME + // TODO pass the hostname in the constructor os with a setter + ni->hostname = "C33_eth"; +#endif + ni->name[0] = CEth::eth_ifname_prefix; + ni->name[1] = '0' + CEth::eth_id++; + ni->mtu = 1500; // FIXME get this from the network + ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - int rv = CEspControl::getInstance().startSoftAccessPoint(cfg); - if (rv == ESP_CONTROL_OK) { - CEspControl::getInstance().getSoftAccessPointConfig(soft_ap_cfg); - wifi_status = WL_AP_LISTENING; - if (net_ifs[NI_WIFI_SOFTAP] != nullptr) { - net_ifs[NI_WIFI_SOFTAP]->setLinkUp(); - } - } else { - wifi_status = WL_AP_FAILED; - } - CLwipIf::getInstance().restartAsyncRequest(); + memcpy(ni->hwaddr, this->driver->getMacAddress(), 6); // FIXME handle this using a constant + // ni->hwaddr = C33EthernetDriver.getMacAddress(); + // ni->hwaddr_len = sizeof(macaddress); + ni->hwaddr_len = 6; - return rv; -} + ni->output = etharp_output; + ni->linkoutput = _netif_output; -/* -------------------------------------------------------------------------- */ -int CLwipIf::setLowPowerMode() -{ - /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().startSyncRequest(); - int rv = CEspControl::getInstance().setPowerSaveMode(1); - CLwipIf::getInstance().restartAsyncRequest(); - return rv; + return ERR_OK; } -/* -------------------------------------------------------------------------- */ -int CLwipIf::resetLowPowerMode() -{ - /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().startSyncRequest(); - int rv = CEspControl::getInstance().setPowerSaveMode(0); - CLwipIf::getInstance().restartAsyncRequest(); - return rv; -} +err_t CEth::output(struct netif* ni, struct pbuf* p) { + err_t errval = ERR_OK; -#ifdef LWIP_USE_TIMER -/* -------------------------------------------------------------------------- */ -void CLwipIf::timer_cb(timer_callback_args_t *arg) { -/* -------------------------------------------------------------------------- */ - (void)arg; - CLwipIf::getInstance().lwip_task(); -} -#endif + /* TODO check if this makes sense, I may get a pbuf chain + * it could happen that if I get a pbuf chain + * - there are enough tx_buffers available to accomodate all the packets in the chain + * - most of the chain is enqueued for delivery, but a certain point the driver.send call returns error + * then lwip is supposed to handle that, that may be an issue + */ + struct pbuf *q = p; + do { + NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); + NETIF_STATS_TX_TIME_START(this->stats); + auto err = C33EthernetDriver.send((uint8_t*)q->payload, q->len); + if(err != 0) { + NETIF_STATS_INCREMENT_ERROR(this->stats, err); + NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + errval = ERR_IF; + break; + } + NETIF_STATS_INCREMENT_TX_BYTES(this->stats, q->len); + NETIF_STATS_TX_TIME_AVERAGE(this->stats); + q = q->next; -/* *************************************************************************** - * DNS related functions - * ****************************************************************************/ + // FIXME remove this, only purpose is to verify if I ever deal with a pbuf chain + // if(q!=nullptr) { + // NETIF_STATS_INCREMENT_ERROR(this->stats, 1024); + // } + } while(q != nullptr && errval != ERR_OK); -/* -------------------------------------------------------------------------- */ -void CLwipIf::dns_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { -/* -------------------------------------------------------------------------- */ - (void)name; - if (ipaddr != NULL) { - *((uint32_t *)callback_arg) = ip4_addr_get_u32(ipaddr); - } else { - *((uint32_t *)callback_arg) = 0; - } + return errval; } -/* -------------------------------------------------------------------------- */ -int8_t CLwipIf::get_ip_address_from_hostname(const char* hostname, uint32_t* ipaddr) -{ - /* -------------------------------------------------------------------------- */ - ip_addr_t iphost; - err_t err; - unsigned long dns_request_sent = 0; - int8_t ret = 0; +void CEth::consume_callback(uint8_t* buffer, uint32_t len) { + // TODO understand if this callback can be moved into the base class + // arduino::lock(); - *ipaddr = 0; - err = dns_gethostbyname(hostname, &iphost, &dns_callback, ipaddr); + const uint16_t trimmed_size = len; - switch (err) { - case ERR_OK: - *ipaddr = ip4_addr_get_u32(&iphost); - ret = 1; - break; + // zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, 1536); + zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, trimmed_size); - case ERR_INPROGRESS: - dns_request_sent = millis(); - while (*ipaddr == 0) { - lwip_task(); - if ((millis() - dns_request_sent) >= TIMEOUT_DNS_REQUEST) { - ret = -1; - break; - } - } + // mem_trim should be passed as an argument, since it depends on the kind of allocation performed + void* buf = mem_trim(buffer, trimmed_size); - if (ret == 0) { - if (*ipaddr == 0) { - ret = -2; - } else { - ret = 1; - } - } - break; + // TODO consider allocating a custom pool for RX or use PBUF_POOL + struct pbuf *p = pbuf_alloced_custom( + PBUF_RAW, len, PBUF_RAM, &custom_pbuf->p, buffer, trimmed_size); - case ERR_ARG: - ret = -4; - break; + err_t err = this->ni.input((struct pbuf*)p, &this->ni); + if (err != ERR_OK) { + NETIF_STATS_INCREMENT_ERROR(this->stats, err); - default: - ret = -4; - break; + NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); + NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); + pbuf_free((struct pbuf*)p); + } else { + NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); } + // arduino::unlock(); +} - return ret; +/* ########################################################################## */ +/* CWifiStation NETWORK INTERFACE CLASS */ +/* ########################################################################## */ +uint8_t CWifiStation::wifistation_id = 0; + +CWifiStation::CWifiStation() +: hw_init(false) { + // TODO this class should implement the driver interface + // CLwipIf::getInstance() } -/* -------------------------------------------------------------------------- */ -int CLwipIf::getHostByName(const char* aHostname, IPAddress& aResult) -{ - /* -------------------------------------------------------------------------- */ - int ret = 0; - uint32_t ipResult = 0; - - // See if it's a numeric IP address - if (inet2aton(aHostname, aResult)) { - // It is, our work here is done - return 1; +int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { // TODO This should be called only once, make it private + int res = 0; + int time_num = 0; + + // arduino::lock(); + CEspControl::getInstance().listenForStationDisconnectEvent([this] (CCtrlMsgWrapper *resp) -> int { + netif_set_link_down(&this->ni); + return ESP_CONTROL_OK; + }); + CEspControl::getInstance().listenForInitEvent([this] (CCtrlMsgWrapper *resp) -> int { + // Serial.println("init"); + this->hw_init = true; + return ESP_CONTROL_OK; + }); + + if ((res=CEspControl::getInstance().initSpiDriver()) != 0) { + res = -1; // FIXME put a proper error code + goto exit; } - if (getDns(0) == IPAddress(0, 0, 0, 0)) { - return INVALID_SERVER; + while (time_num < 100 && !hw_init) { // TODO #define WIFI_INIT_TIMEOUT_MS 10000 + CEspControl::getInstance().communicateWithEsp(); + R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS); + time_num++; } -#if LWIP_DNS - ret = get_ip_address_from_hostname(aHostname, &ipResult); - aResult = IPAddress(ipResult); -#endif - return ret; + res = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); + CNetif::begin(ip, nm, gw); + // netif_set_link_up(&this->ni); // TODO this should be set only when successfully connected to an AP +exit: + // arduino::unlock(); + return res; } -/* -------------------------------------------------------------------------- */ -int CLwipIf::inet2aton(const char* address, IPAddress& result) -{ - /* -------------------------------------------------------------------------- */ - uint16_t acc = 0; // Accumulator - uint8_t dots = 0; +int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { + WifiApCfg_t ap; + int rv = ESP_CONTROL_CTRL_ERROR; // FIXME this should be set with an error meaning AP not found + bool found = false; + int8_t best_index = -1; // this index is used to find the ap with the best rssi + // AccessPoint_t* best_matching_ap; + // arduino::lock(); - if (address == NULL) { - return 0; + // if(access_points.size() == 0) { + // this->scanForAp(); + // } + if((rv=this->scanForAp()) != WL_SCAN_COMPLETED) { + // rv = -1; // FIXME set proper error code + goto exit; + } + this->printAps(); + + // find the AP with the best rssi + for (uint8_t i = 0; i < access_points.size(); i++) { + if(strcmp(ssid, (const char*)access_points[i].ssid) == 0 + && (best_index == -1 || access_points[best_index].rssi < access_points[i].rssi) + ) { + best_index=i; + } } + if(best_index != -1) { + // memset(ap.ssid, 0x00, SSID_LENGTH); // I shouldn't need to zero the ssid string pointer + strncpy((char*)ap.ssid, ssid, SSID_LENGTH); + // memcpy(ap.ssid, access_points[best_index].ssid, SSID_LENGTH); - while (*address) { - char c = *address++; - if (c >= '0' && c <= '9') { - acc = acc * 10 + (c - '0'); - if (acc > 255) { - // Value out of [0..255] range - return 0; - } - } else if (c == '.') { - if (dots == 3) { - // Too much dots (there must be 3 dots) - return 0; - } - result[dots++] = acc; - acc = 0; + // memset(ap.pwd, 0x00, PASSWORD_LENGTH); + if(passphrase != nullptr) { + auto slen = strlen(passphrase)+1; + strncpy((char*)ap.pwd, passphrase, (slen < PASSWORD_LENGTH) ? slen : PASSWORD_LENGTH); + // memcpy(ap.pwd, passphrase, (slen < PASSWORD_LENGTH) ? slen : PASSWORD_LENGTH); } else { - // Invalid char - return 0; + // memset(ap.pwd, 0x00, PASSWORD_LENGTH); + ap.pwd[0] = '\0'; } - } - if (dots != 3) { - // Too few dots (there must be 3 dots) - return 0; - } - result[3] = acc; - return 1; -} + memset(ap.bssid, 0x00, BSSID_LENGTH); + memcpy(ap.bssid, access_points[best_index].bssid, BSSID_LENGTH); -/* -------------------------------------------------------------------------- */ -void CLwipIf::beginDns(IPAddress aDNSServer) -{ - /* -------------------------------------------------------------------------- */ - addDns(aDNSServer); -} + // arduino::lock(); + CEspControl::getInstance().communicateWithEsp(); // TODO make this shared between SoftAP and station + rv=CEspControl::getInstance().connectAccessPoint(ap); + // arduino::unlock(); + if (rv == ESP_CONTROL_OK) { + CEspControl::getInstance().getAccessPointConfig(access_point_cfg); -/* -------------------------------------------------------------------------- */ -void CLwipIf::addDns(IPAddress aDNSServer) -{ - /* -------------------------------------------------------------------------- */ -#if LWIP_DNS - ip_addr_t ip; - dns_num++; - /* DNS initialized by DHCP when call dhcp_start() */ - bool dhcp_started = false; - - for (int i = 0; i < NETWORK_INTERFACES_MAX_NUM; i++) { - if (net_ifs[i] != nullptr) { - if (net_ifs[i]->DhcpIsStarted()) { - dhcp_started = true; - break; - } + netif_set_link_up(&this->ni); } + // arduino::unlock(); } + // else { + // // TODO return AP not found error + // } - if (!dhcp_started) { - dns_init(); - IP_ADDR4(&ip, aDNSServer[0], aDNSServer[1], aDNSServer[2], aDNSServer[3]); - dns_setserver(dns_num, &ip); - } -#endif +exit: + // arduino::unlock(); + + return rv; } -/* -------------------------------------------------------------------------- */ -IPAddress CLwipIf::getDns(int _num) -{ - /* -------------------------------------------------------------------------- */ -#if LWIP_DNS - const ip_addr_t* tmp = dns_getserver(_num); - return IPAddress(ip4_addr_get_u32(tmp)); -#else - IPAddress(0, 0, 0, 0); -#endif +// disconnect +int CWifiStation::disconnectFromAp() { + return CEspControl::getInstance().disconnectAccessPoint(); } +err_t CWifiStation::init(struct netif* ni) { + // Setting up netif +#if LWIP_NETIF_HOSTNAME + // TODO pass the hostname in the constructor os with a setter + ni->hostname = "C33-WifiSta"; +#endif + ni->name[0] = CWifiStation::wifistation_ifname_prefix; + ni->name[1] = '0' + CWifiStation::wifistation_id++; + ni->mtu = 1500; // FIXME get this from the network + ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + WifiMac_t MAC; + MAC.mode = WIFI_MODE_STA; + CEspControl::getInstance().getWifiMacAddress(MAC); + CNetUtilities::macStr2macArray(ni->hwaddr, MAC.mac); + ni->hwaddr_len = 6; // FIXME this should be a macro defined somewhere + // ni->hwaddr_len = CLwipIf::getInstance().getMacAddress(NI_WIFI_STATION, ni->hwaddr); + ni->output = etharp_output; + ni->linkoutput = _netif_output; -/* -------------------------------------------------------------------------- */ -const char* CLwipIf::getSSID(NetIfType_t type) -{ - /* -------------------------------------------------------------------------- */ - if (type == NI_WIFI_STATION) { - return (char*)access_point_cfg.ssid; - } else if (type == NI_WIFI_SOFTAP) { - return (char*)soft_ap_cfg.ssid; - } else { - return nullptr; - } + return ERR_OK; } -/* -------------------------------------------------------------------------- */ -uint8_t* CLwipIf::getBSSID(NetIfType_t type, uint8_t* bssid) -{ - /* -------------------------------------------------------------------------- */ - if (type == NI_WIFI_STATION) { - CNetUtilities::macStr2macArray(bssid, (const char*)access_point_cfg.bssid); - return bssid; - } else if (type == NI_WIFI_SOFTAP) { - CNetUtilities::macStr2macArray(bssid, (const char*)soft_ap_cfg.out_mac); - return bssid; +err_t CWifiStation::output(struct netif* _ni, struct pbuf* p) { + // FIXME set ifn + int ifn = 0; // interface number in CNetif.cpp seems to not be set anywhere + uint8_t *buf = nullptr; + uint16_t size=p->tot_len; + err_t errval = ERR_IF; + int err = ESP_CONTROL_OK; + + NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); + NETIF_STATS_TX_TIME_START(this->stats); + + // arduino::lock(); + // p may be a chain of pbufs + if(p->next != nullptr) { + buf = (uint8_t*) malloc(size*sizeof(uint8_t)); + if(buf == nullptr) {\ + NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); + NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + errval = ERR_MEM; + goto exit; + } + + // copy the content of pbuf + assert(pbuf_copy_partial(p, buf, size, 0) == size); } else { - return nullptr; + buf = (uint8_t*)p->payload; } -} -/* -------------------------------------------------------------------------- */ -int32_t CLwipIf::getRSSI(NetIfType_t type) -{ - /* -------------------------------------------------------------------------- */ - if (type == NI_WIFI_STATION) { - return access_point_cfg.rssi; + // sendBuffer makes a memcpy of buffer + // TODO send buffer should handle the buffer deletion and avoid a memcpy + if ((err = CEspControl::getInstance().sendBuffer( + ESP_STA_IF, ifn, buf, size)) == ESP_CONTROL_OK) { + errval = ERR_OK; + NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); + NETIF_STATS_TX_TIME_AVERAGE(this->stats); } else { - return 0; + NETIF_STATS_INCREMENT_ERROR(this->stats, err); + NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); } -} -/* -------------------------------------------------------------------------- */ -uint8_t CLwipIf::getEncryptionType(NetIfType_t type) -{ - /* -------------------------------------------------------------------------- */ - if (type == NI_WIFI_STATION) { - return Encr2wl_enc(access_point_cfg.encryption_mode); - } else if (type == NI_WIFI_SOFTAP) { - return Encr2wl_enc((uint8_t)soft_ap_cfg.encryption_mode); - } else { - return ENC_TYPE_UNKNOWN; +exit: + if(p->next != nullptr && buf != nullptr) { + free(buf); } + // arduino::unlock(); + return errval; } -/* ########################################################################## */ -/* BASE NETWORK INTERFACE CLASS */ -/* ########################################################################## */ - -/* -------------------------------------------------------------------------- */ -CNetIf::CNetIf() - : dhcp_timeout(30000) - , dhcp_started(false) - , dhcp_acquired(false) - , id(0) - , dhcp_st(DHCP_IDLE_STATUS) - , _dhcp_lease_state(DHCP_CHECK_NONE) -{ - /* -------------------------------------------------------------------------- */ - memset(hostname, 0x00, MAX_HOSTNAME_DIM); - hostname[0] = 'C'; - hostname[1] = '3'; - hostname[2] = '3'; -#if LWIP_NETIF_HOSTNAME - ni.hostname = (const char*)&hostname; -#endif -#ifdef CNETWORK_INTERFACE_DEBUG - Serial.println("[CNET]: CNetIf constructor"); -#endif -} +void CWifiStation::task() { + // calling the base class task, in order to make thigs work + CNetif::task(); -/* -------------------------------------------------------------------------- */ -CNetIf::~CNetIf() -{ - /* -------------------------------------------------------------------------- */ -#ifdef CNETWORK_INTERFACE_DEBUG - Serial.println("[CNET]: CNetIf destructor"); -#endif -} + // TODO in order to make things easier this should be implemented inside of Wifi driver + // and not override LWIPInterface method -/* *************************************************************************** - * DHCP related functions - * ****************************************************************************/ + uint8_t if_num = 0; + uint16_t dim = 0; + uint8_t* buffer = nullptr; + struct pbuf* p = nullptr; -/* -------------------------------------------------------------------------- */ -void CNetIf::DhcpNotUsed() -{ - /* -------------------------------------------------------------------------- */ - DhcpStop(); - dhcp_inform(getNi()); -} + NETIF_STATS_RX_TIME_START(this->stats); + // arduino::lock(); + // TODO do not perform this when not connected to an AP + if(hw_init) { + CEspControl::getInstance().communicateWithEsp(); // TODO make this shared between SoftAP and station -/* -------------------------------------------------------------------------- */ -int CNetIf::checkLease() -{ - /* -------------------------------------------------------------------------- */ - int rc = DHCP_CHECK_NONE; + // TODO handling buffer this way may be harmful for the memory + buffer = CEspControl::getInstance().getStationRx(if_num, dim); + } - task(); - rc = dhcp_get_lease_state(); + // empty the ESP32 queue + while(buffer != nullptr) { + // FIXME this section is redundant and should be generalized toghether with CEth::consume_callback + // TODO understand if this should be moved into the base class + NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); + // NETIF_STATS_RX_TIME_START(this->stats); - if (rc != _dhcp_lease_state) { - switch (_dhcp_lease_state) { - case DHCP_CHECK_NONE: - _dhcp_lease_state = rc; - rc = DHCP_CHECK_NONE; - break; + zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, dim, free); - case DHCP_CHECK_RENEW_OK: - _dhcp_lease_state = rc; - if (rc == DHCP_CHECK_NONE) { - rc = DHCP_CHECK_RENEW_OK; - } else { - rc = DHCP_CHECK_RENEW_FAIL; - } - break; + // TODO consider allocating a custom pool for RX or use PBUF_POOL + struct pbuf *p = pbuf_alloced_custom( + PBUF_RAW, dim, PBUF_RAM, &custom_pbuf->p, buffer, dim); - case DHCP_CHECK_REBIND_OK: - _dhcp_lease_state = rc; - if (rc == DHCP_CHECK_NONE) { - rc = DHCP_CHECK_REBIND_OK; - } else { - rc = DHCP_CHECK_REBIND_FAIL; - } - break; + err_t err = this->ni.input((struct pbuf*)p, &this->ni); + if (err != ERR_OK) { + NETIF_STATS_INCREMENT_ERROR(this->stats, err); - default: - _dhcp_lease_state = DHCP_CHECK_NONE; - break; + NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); + NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); + pbuf_free((struct pbuf*)p); + } else { + NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); } - } - - return rc; -} -/* -------------------------------------------------------------------------- */ -uint8_t CNetIf::dhcp_get_lease_state() -{ - /* -------------------------------------------------------------------------- */ - uint8_t res = 0; - struct dhcp* dhcp = (struct dhcp*)netif_get_client_data(getNi(), LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); - - if (dhcp->state == 5 /*DHCP_STATE_RENEWING*/) { - res = 2; - } else if (dhcp->state == 4 /* DHCP_STATE_REBINDING */) { - res = 4; + buffer = CEspControl::getInstance().getStationRx(if_num, dim); + // NETIF_STATS_RX_TIME_AVERAGE(this->stats); } - return res; + NETIF_STATS_RX_TIME_AVERAGE(this->stats); + // arduino::unlock(); } -/* -------------------------------------------------------------------------- */ -bool CNetIf::dhcp_request() -{ - /* -------------------------------------------------------------------------- */ - /* make a DHCP request: it runs till an address is acquired or a timeout - expires */ - unsigned long startTime = millis(); - bool acquired = false; - - do { - acquired = isDhcpAcquired(); - if (!acquired && ((millis() - startTime) > dhcp_timeout)) { - break; - } - - } while (!acquired); - - return acquired; +void CWifiStation::consume_callback(uint8_t* buffer, uint32_t len) { + // FIXME take what is written in task and put it in here } -/* -------------------------------------------------------------------------- */ -void CNetIf::dhcp_reset() -{ - /* -------------------------------------------------------------------------- */ - /* it resets the DHCP status to IDLE */ - while (dhcp_st != DHCP_IDLE_STATUS) { - task(); - } +const char* CWifiStation::getSSID() { + return (const char*)access_point_cfg.ssid; } -/* -------------------------------------------------------------------------- */ -void CNetIf::DhcpSetTimeout(unsigned long t) -{ - /* -------------------------------------------------------------------------- */ - dhcp_timeout = t; +uint8_t* CWifiStation::getBSSID(uint8_t* bssid){ + CNetUtilities::macStr2macArray(bssid, (const char*)access_point_cfg.bssid); + return bssid; } -/* -------------------------------------------------------------------------- */ -bool CNetIf::isDhcpAcquired() -{ - return dhcp_acquired; -} -/* -------------------------------------------------------------------------- */ -bool CNetIf::DhcpStart() -{ - /* first stop / reset */ - DhcpStop(); - /* then actually start */ - dhcp_started = true; - dhcp_st = DHCP_START_STATUS; - return dhcp_request(); -} -/* -------------------------------------------------------------------------- */ -void CNetIf::DhcpStop() -{ - /* -------------------------------------------------------------------------- */ - dhcp_started = false; - if (dhcp_st == DHCP_IDLE_STATUS) { - return; - } - if (dhcp_st == DHCP_GOT_STATUS && netif_is_link_up(getNi())) { - dhcp_st = DHCP_RELEASE_STATUS; - } else { - dhcp_st = DHCP_STOP_STATUS; - } - dhcp_reset(); +int32_t CWifiStation::getRSSI() { + // TODO should this be updated? + return (uint32_t)access_point_cfg.rssi; } -/* -------------------------------------------------------------------------- */ -void CNetIf::dhcp_task() -{ - /* -------------------------------------------------------------------------- */ - struct dhcp* lwip_dhcp; - static unsigned long DHCPStartTime; - - switch (dhcp_st) { - case DHCP_IDLE_STATUS: - /* nothing to do... wait for DhcpStart() to start the process */ - break; - case DHCP_START_STATUS: - if (netif_is_link_up(getNi())) { - ip_addr_set_zero_ip4(&(getNi()->ip_addr)); - ip_addr_set_zero_ip4(&(getNi()->netmask)); - ip_addr_set_zero_ip4(&(getNi()->gw)); - /* start lwIP dhcp */ - dhcp_start(getNi()); - - DHCPStartTime = millis(); - dhcp_st = DHCP_WAIT_STATUS; - } - break; - case DHCP_WAIT_STATUS: - if (netif_is_link_up(getNi())) { - if (dhcp_supplied_address(getNi())) { - dhcp_acquired = true; - dhcp_st = DHCP_GOT_STATUS; - } else if (millis() - DHCPStartTime > 1000) { - /* TIMEOUT */ - lwip_dhcp = (struct dhcp*)netif_get_client_data(getNi(), LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); - if (lwip_dhcp->tries > MAX_DHCP_TRIES) { - dhcp_st = DHCP_STOP_STATUS; - } - } - } else { - dhcp_st = DHCP_START_STATUS; - } - break; - case DHCP_GOT_STATUS: - if (!netif_is_link_up(getNi())) { - dhcp_st = DHCP_STOP_STATUS; - } - - break; - case DHCP_RELEASE_STATUS: - dhcp_release(getNi()); - dhcp_acquired = false; - dhcp_st = DHCP_STOP_STATUS; - break; - case DHCP_STOP_STATUS: - dhcp_acquired = false; - dhcp_stop(getNi()); - if (dhcp_started) { - dhcp_st = DHCP_START_STATUS; - } else { - dhcp_st = DHCP_IDLE_STATUS; - } - break; - } +uint8_t CWifiStation::getEncryptionType() { + return Encr2wl_enc(access_point_cfg.encryption_mode); } -/* -------------------------------------------------------------------------- */ -void CNetIf::setLinkUp() -{ - /* -------------------------------------------------------------------------- */ - netif_set_link_up(&ni); - /* When the netif is fully configured this function must be called.*/ - netif_set_up(&ni); -} +// int CWifiStation::getMacAddress(uint8_t* mac) { +// } -/* -------------------------------------------------------------------------- */ -void CNetIf::setLinkDown() -{ - /* -------------------------------------------------------------------------- */ - netif_set_link_down(&ni); - /* When the netif is fully configured this function must be called.*/ - netif_set_down(&ni); -} +// uint8_t CWifiStation::getChannel() { +// return (uint8_t)access_point_cfg.channel; +// } /* ########################################################################## */ -/* ETHERNET NETWORK INTERFACE CLASS */ +/* CWifiSoftAp NETWORK INTERFACE CLASS */ /* ########################################################################## */ -CEth::CEth() { } -CEth::~CEth() { } -/* -------------------------------------------------------------------------- */ -void CEth::begin(IPAddress _ip, IPAddress _gw, IPAddress _nm) -{ - if (_ip == INADDR_NONE) { - _ip = default_ip; - _nm = default_nm; - _gw = default_gw; - } - IP_ADDR4(&ip, _ip[0], _ip[1], _ip[2], _ip[3]); - IP_ADDR4(&nm, _nm[0], _nm[1], _nm[2], _nm[3]); - IP_ADDR4(&gw, _gw[0], _gw[1], _gw[2], _gw[3]); +CWifiSoftAp::CWifiSoftAp() { } +CWifiSoftAp::~CWifiSoftAp() { } - netif_add(&ni, &ip, &nm, &gw, NULL, CEth::init, ethernet_input); - netif_set_default(&ni); +uint8_t CWifiSoftAp::softap_id = 0; - if (netif_is_link_up(&ni)) { - /* When the netif is fully configured this function must be called */ - netif_set_up(&ni); - } else { - /* When the netif link is down this function must be called */ - netif_set_down(&ni); - } +// This is required for dhcp server to assign ip addresses to AP clients +IPAddress default_nm("255.255.255.0"); +IPAddress default_dhcp_server_ip("192.168.4.1"); + +CWifiSoftAp::CWifiSoftAp() +: hw_init(false) { -#if LWIP_NETIF_LINK_CALLBACK - /* Set the link callback function, this function is called on change of link status */ - // netif_set_link_callback(ð0if, eht0if_link_toggle_cbk); -#endif /* LWIP_NETIF_LINK_CALLBACK */ - /* - * set the callback function that is called when an ethernet frame is physically - * received, it is important that the callbacks are set before the initializiation - */ - eth_set_rx_frame_cbk(std::bind(&CEth::handleEthRx, this)); - eth_set_link_on_cbk(std::bind(&CEth::setLinkUp, this)); - eth_set_link_off_cbk(std::bind(&CEth::setLinkDown, this)); } -/* -------------------------------------------------------------------------- */ -void CEth::task() -{ - /* -------------------------------------------------------------------------- */ +int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { // TODO use provided ip address, instead of default ones + int res = 0; + int time_num = 0; - eth_execute_link_process(); + // arduino::lock(); + CEspControl::getInstance().listenForInitEvent([this] (CCtrlMsgWrapper *resp) -> int { + // Serial.println("init"); + this->hw_init = true; + return ESP_CONTROL_OK; + }); -#if LWIP_DHCP - static unsigned long dhcp_last_time_call = 0; - if (dhcp_last_time_call == 0 || millis() - dhcp_last_time_call > DHCP_FINE_TIMER_MSECS) { - dhcp_task(); - dhcp_last_time_call = millis(); + if ((res=CEspControl::getInstance().initSpiDriver()) != 0) { + // res = -1; // FIXME put a proper error code + goto exit; } -#endif -} -/* ########################################################################## */ -/* CWifiStation NETWORK INTERFACE CLASS */ -/* ########################################################################## */ + while (time_num < 100 && !hw_init) { // TODO #define WIFI_INIT_TIMEOUT_MS 10000 + CEspControl::getInstance().communicateWithEsp(); + R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS); + time_num++; + } -CWifiStation::CWifiStation() { } -CWifiStation::~CWifiStation() { } + res = CEspControl::getInstance().setWifiMode(WIFI_MODE_AP); -void CWifiStation::begin(IPAddress _ip, IPAddress _gw, IPAddress _nm) -{ - if (_ip == INADDR_NONE) { - _ip = default_ip; - _nm = default_nm; - _gw = default_gw; - } - IP_ADDR4(&ip, _ip[0], _ip[1], _ip[2], _ip[3]); - IP_ADDR4(&nm, _nm[0], _nm[1], _nm[2], _nm[3]); - IP_ADDR4(&gw, _gw[0], _gw[1], _gw[2], _gw[3]); + // netif_set_link_up(&this->ni); // TODO this should be set only when successfully connected to an AP + CNetif::begin( + default_dhcp_server_ip, + default_nm, + default_dhcp_server_ip + ); +exit: + // arduino::unlock(); + return res; +} - netif_add(&ni, &ip, &nm, &gw, NULL, CWifiStation::init, ethernet_input); - netif_set_default(&ni); +// TODO scan the other access point first and then set the channel if 0 +// TODO there are requirements for ssid and password +int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t channel) { + SoftApCfg_t cfg; - if (netif_is_link_up(&ni)) { - /* When the netif is fully configured this function must be called */ - netif_set_up(&ni); + strncpy((char*)cfg.ssid, ssid, SSID_LENGTH); + + if (passphrase == nullptr) { + cfg.pwd[0] = '\0'; + cfg.encryption_mode = WIFI_AUTH_OPEN; } else { - /* When the netif link is down this function must be called */ - netif_set_down(&ni); + auto slen = strlen(passphrase)+1; + strncpy((char*)cfg.pwd, passphrase, (slen < PASSWORD_LENGTH) ? slen : PASSWORD_LENGTH); + + cfg.encryption_mode = WIFI_AUTH_WPA_WPA2_PSK; } -#if LWIP_NETIF_LINK_CALLBACK - /* Set the link callback function, this function is called on change of link status */ - // netif_set_link_callback(ð0if, eht0if_link_toggle_cbk); -#endif /* LWIP_NETIF_LINK_CALLBACK */ -} + channel = (channel == 0) ? 1 : channel; + cfg.channel = (channel > MAX_CHNL_NO) ? MAX_CHNL_NO : channel; + cfg.max_connections = 10; // FIXME + // cfg.max_connections = MAX_SOFAT_CONNECTION_DEF; // FIXME + cfg.bandwidth = WIFI_BW_HT40; + cfg.ssid_hidden = false; -/* -------------------------------------------------------------------------- */ -void CWifiStation::task() -{ - /* -------------------------------------------------------------------------- */ - /* get messages and process it */ - uint8_t if_num; - uint16_t dim = 0; - uint8_t* buf = nullptr; - struct pbuf* p = nullptr; + int rv = CEspControl::getInstance().startSoftAccessPoint(cfg); + if (rv == ESP_CONTROL_OK) { + CEspControl::getInstance().getSoftAccessPointConfig(soft_ap_cfg); + // wifi_status = WL_AP_LISTENING; + netif_set_link_up(&this->ni); - /* shall we verify something about if_num??? */ - do { - dim = CEspControl::getInstance().peekStationRxMsgSize(); - if (dim > 0) - { - p = pbuf_alloc(PBUF_RAW, dim, PBUF_RAM); - if (p != nullptr) - { - buf = CEspControl::getInstance().getStationRx(if_num, dim); - /* Copy ethernet frame into pbuf */ - pbuf_take((struct pbuf*)p, (uint8_t*)buf, (uint32_t)dim); - if (ni.input(p, &ni) != ERR_OK) { - pbuf_free(p); - } - delete[] buf; - } - } - } while(dim > 0 && p != nullptr); + // FIXME the dhcp server should be started somewhere else + dhcps_start(&(this->ni)); + } else { + // wifi_status = WL_AP_FAILED; + } -#if LWIP_DHCP - static unsigned long dhcp_last_time_call = 0; - if (dhcp_last_time_call == 0 || millis() - dhcp_last_time_call > DHCP_FINE_TIMER_MSECS) { - dhcp_task(); - dhcp_last_time_call = millis(); - } -#endif + return rv; } -/* -------------------------------------------------------------------------- */ -int CWifiStation::getMacAddress(uint8_t* mac) { -/* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getMacAddress(NI_WIFI_STATION, mac); -} +int CWifiSoftAp::stopSoftAp() { -/* -------------------------------------------------------------------------- */ -const char* CWifiStation::getSSID() -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getSSID(NI_WIFI_STATION); } -/* -------------------------------------------------------------------------- */ -uint8_t* CWifiStation::getBSSID(uint8_t* bssid) -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getBSSID(NI_WIFI_STATION, bssid); -} +err_t CWifiSoftAp::init(struct netif* ni) { + // Setting up netif +#if LWIP_NETIF_HOSTNAME + // TODO pass the hostname in the constructor os with a setter + ni->hostname = "C33-SoftAP"; +#endif + ni->name[0] = CWifiSoftAp::softap_ifname_prefix; + ni->name[1] = '0' + CWifiSoftAp::softap_id++; + ni->mtu = 1500; // FIXME get this from the network + ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; -/* -------------------------------------------------------------------------- */ -int32_t CWifiStation::getRSSI() -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getRSSI(NI_WIFI_STATION); -} + WifiMac_t MAC; + MAC.mode = WIFI_MODE_AP; + CEspControl::getInstance().getWifiMacAddress(MAC); + CNetUtilities::macStr2macArray(ni->hwaddr, MAC.mac); + ni->hwaddr_len = 6; // FIXME this should be a macro defined somewhere -/* -------------------------------------------------------------------------- */ -uint8_t CWifiStation::getEncryptionType() -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getEncryptionType(NI_WIFI_STATION); + ni->output = etharp_output; + ni->linkoutput = _netif_output; + + return ERR_OK; } -/* ########################################################################## */ -/* CWifiSoftAp NETWORK INTERFACE CLASS */ -/* ########################################################################## */ +err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { + // FIXME set ifn + int ifn = 0; // interface number in CNetif.cpp seems to not be set anywhere + uint8_t *buf = nullptr; + uint16_t size=p->tot_len; + err_t errval = ERR_IF; + int err = ESP_CONTROL_OK; -CWifiSoftAp::CWifiSoftAp() { } -CWifiSoftAp::~CWifiSoftAp() { } + NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); + NETIF_STATS_TX_TIME_START(this->stats); -void CWifiSoftAp::begin(IPAddress _ip, IPAddress _gw, IPAddress _nm) -{ - if (_ip == INADDR_NONE) { - _ip = default_dhcp_server_ip; - _nm = default_nm; - _gw = default_dhcp_server_ip; + // arduino::lock(); + // p may be a chain of pbufs + if(p->next != nullptr) { + buf = (uint8_t*) malloc(size*sizeof(uint8_t)); + if(buf == nullptr) {\ + NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); + NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + errval = ERR_MEM; + goto exit; + } + + // copy the content of pbuf + assert(pbuf_copy_partial(p, buf, size, 0) == size); + } else { + buf = (uint8_t*)p->payload; } - IP_ADDR4(&ip, _ip[0], _ip[1], _ip[2], _ip[3]); - IP_ADDR4(&nm, _nm[0], _nm[1], _nm[2], _nm[3]); - IP_ADDR4(&gw, _gw[0], _gw[1], _gw[2], _gw[3]); - - netif_add(&ni, &ip, &nm, &gw, NULL, CWifiSoftAp::init, ethernet_input); - netif_set_default(&ni); - if (netif_is_link_up(&ni)) { - /* When the netif is fully configured this function must be called */ - netif_set_up(&ni); + + // sendBuffer makes a memcpy of buffer + // TODO send buffer should handle the buffer deletion and avoid a memcpy + if ((err = CEspControl::getInstance().sendBuffer( + ESP_AP_IF, ifn, buf, size)) == ESP_CONTROL_OK) { + errval = ERR_OK; + NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); + NETIF_STATS_TX_TIME_AVERAGE(this->stats); } else { - /* When the netif link is down this function must be called */ - netif_set_down(&ni); + NETIF_STATS_INCREMENT_ERROR(this->stats, err); + NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); } -#if LWIP_NETIF_LINK_CALLBACK - /* Set the link callback function, this function is called on change of link status */ - // netif_set_link_callback(ð0if, eht0if_link_toggle_cbk); -#endif /* LWIP_NETIF_LINK_CALLBACK */ +exit: + if(p->next != nullptr && buf != nullptr) { + free(buf); + } + // arduino::unlock(); + return errval; } -/* -------------------------------------------------------------------------- */ -void CWifiSoftAp::task() -{ - /* -------------------------------------------------------------------------- */ - /* get messages and process it - * TODO change the algorithm and make it similar to WiFiStation */ - uint8_t if_num; - uint16_t dim; - uint8_t* buf = nullptr; - /* shall we verify something about if_num??? */ - do { +void CWifiSoftAp::task() { + // calling the base class task, in order to make thigs work + CNetif::task(); - buf = CEspControl::getInstance().getSoftApRx(if_num, dim); + // TODO in order to make things easier this should be implemented inside of Wifi driver + // and not override LWIPInterface method - if (buf != nullptr) { - struct pbuf* p = pbuf_alloc(PBUF_RAW, dim, PBUF_RAM); - if (p != NULL) { - /* Copy ethernet frame into pbuf */ - pbuf_take((struct pbuf*)p, (uint8_t*)buf, (uint32_t)dim); - delete[] buf; + uint8_t if_num = 0; + uint16_t dim = 0; + uint8_t* buffer = nullptr; + struct pbuf* p = nullptr; - if (ni.input(p, &ni) != ERR_OK) { - pbuf_free(p); - } - } - } - } while(buf != nullptr); + NETIF_STATS_RX_TIME_START(this->stats); + // arduino::lock(); + // TODO do not perform this when not connected to an AP + if(hw_init) { + CEspControl::getInstance().communicateWithEsp(); // TODO make this shared between SoftAP and station -#if LWIP_DHCP - static unsigned long dhcp_last_time_call = 0; - if (dhcp_last_time_call == 0 || millis() - dhcp_last_time_call > DHCP_FINE_TIMER_MSECS) { - dhcp_task(); - dhcp_last_time_call = millis(); + // TODO handling buffer this way may be harmful for the memory + buffer = CEspControl::getInstance().getSoftApRx(if_num, dim); } -#endif -} -/* -------------------------------------------------------------------------- */ -int CWifiSoftAp::getMacAddress(uint8_t* mac) -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getMacAddress(NI_WIFI_SOFTAP, mac); -} + // empty the ESP32 queue + while(buffer != nullptr) { + // FIXME this section is redundant and should be generalized toghether with CEth::consume_callback + // TODO understand if this should be moved into the base class + NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); + // NETIF_STATS_RX_TIME_START(this->stats); -/* -------------------------------------------------------------------------- */ -const char* CWifiSoftAp::getSSID() -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getSSID(NI_WIFI_SOFTAP); + zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, dim, free); + + // TODO consider allocating a custom pool for RX or use PBUF_POOL + struct pbuf *p = pbuf_alloced_custom( + PBUF_RAW, dim, PBUF_RAM, &custom_pbuf->p, buffer, dim); + + err_t err = this->ni.input((struct pbuf*)p, &this->ni); + if (err != ERR_OK) { + NETIF_STATS_INCREMENT_ERROR(this->stats, err); + + NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); + NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); + pbuf_free((struct pbuf*)p); + } else { + NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); + } + + buffer = CEspControl::getInstance().getStationRx(if_num, dim); + // NETIF_STATS_RX_TIME_AVERAGE(this->stats); + } + NETIF_STATS_RX_TIME_AVERAGE(this->stats); + // arduino::unlock(); } -/* -------------------------------------------------------------------------- */ -uint8_t* CWifiSoftAp::getBSSID(uint8_t* bssid) -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getBSSID(NI_WIFI_SOFTAP, bssid); +const char* CWifiSoftAp::getSSID() { + return (const char*)soft_ap_cfg.ssid; } -/* -------------------------------------------------------------------------- */ -int32_t CWifiSoftAp::getRSSI() -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getRSSI(NI_WIFI_SOFTAP); +uint8_t* CWifiSoftAp::getBSSID(uint8_t* bssid){ + // CNetUtilities::macStr2macArray(bssid, (const char*)soft_ap_cfg.bssid); + // return bssid; } -/* -------------------------------------------------------------------------- */ -uint8_t CWifiSoftAp::getEncryptionType() -{ - /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getEncryptionType(NI_WIFI_SOFTAP); +uint8_t CWifiSoftAp::getEncryptionType() { + return Encr2wl_enc(soft_ap_cfg.encryption_mode); } +/* ########################################################################## + * DEBUG UTILS + * ########################################################################## */ #if DHCPS_DEBUG == 1 char b_dbg[512]; From d40a06a92eafb857bf5a2b82f5008e627f702fc8 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:25:06 +0100 Subject: [PATCH 09/79] added possibility to pass a std::function to esphosted callbacks --- libraries/ESPhost/src/CEspCbks.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/ESPhost/src/CEspCbks.h b/libraries/ESPhost/src/CEspCbks.h index 892fc71d..203ce996 100644 --- a/libraries/ESPhost/src/CEspCbks.h +++ b/libraries/ESPhost/src/CEspCbks.h @@ -32,13 +32,14 @@ #include "CCtrlWrapper.h" +#include #define RESPONSE_TABLE_DIM (CTRL_RESP_MAX - CTRL_RESP_BASE) #define EVENT_TABLE_DIM (CTRL_EVENT_MAX - CTRL_EVENT_BASE) #define TOTAL_TABLE_DIM RESPONSE_TABLE_DIM + EVENT_TABLE_DIM -using EspCallback_f = int (*)(CCtrlMsgWrapper *resp); +using EspCallback_f = std::function; From 58c28605c41cbd42ec55fae85d6e6f5a736d9850 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:25:55 +0100 Subject: [PATCH 10/79] defined Ethernet driver and interface instance --- libraries/Ethernet/src/EthernetC33.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/EthernetC33.h b/libraries/Ethernet/src/EthernetC33.h index b2b9e428..4ff7daf0 100644 --- a/libraries/Ethernet/src/EthernetC33.h +++ b/libraries/Ethernet/src/EthernetC33.h @@ -19,8 +19,9 @@ #ifdef ARDUINO_PORTENTA_C33 // TODO Instantiate the drivers for ethernet with default configuration parameters -// EthernetC33Driver C33EthernetDriver(2, 2, mem_malloc, 1536); +inline EthernetC33Driver EthernetDriver(2, 2, mem_malloc, 1536); // FIXME Instantiate a global variable from CEth, calling it Ethernet +inline CEth Ethernet(&EthernetDriver); #endif From 3850758a97d22426e25794b9296b09c9e16a4abf Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:26:34 +0100 Subject: [PATCH 11/79] removed unused endif --- libraries/Ethernet/src/EthernetDriver.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/Ethernet/src/EthernetDriver.h b/libraries/Ethernet/src/EthernetDriver.h index 8af05d6c..64cde03b 100644 --- a/libraries/Ethernet/src/EthernetDriver.h +++ b/libraries/Ethernet/src/EthernetDriver.h @@ -92,7 +92,6 @@ class EthernetC33Driver: public NetworkDriver { virtual void irq_ether_callback(ether_callback_args_t* p_args); friend void _irq_ether_callback(ether_callback_args_t* p_args); -#endif }; extern EthernetC33Driver C33EthernetDriver; \ No newline at end of file From 9784bacc3a7a37b607e36e1623d2912ab5bfcd2d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:26:58 +0100 Subject: [PATCH 12/79] commented netif stats --- libraries/Ethernet/src/EthernetDriver.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/Ethernet/src/EthernetDriver.cpp b/libraries/Ethernet/src/EthernetDriver.cpp index ae69c8a4..6c6b2fb2 100644 --- a/libraries/Ethernet/src/EthernetDriver.cpp +++ b/libraries/Ethernet/src/EthernetDriver.cpp @@ -153,19 +153,19 @@ void EthernetC33Driver::poll() { return; } - netif_stats &stats = *(this->stats); - NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(stats); + // netif_stats &stats = *(this->stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(stats); // arduino::lock(); while(ETHER_RD0_RACT != (ctrl.p_rx_descriptor->status & ETHER_RD0_RACT)) { - NETIF_STATS_RX_TIME_START(stats); // FIXME add stats + // NETIF_STATS_RX_TIME_START(stats); // FIXME add stats // Getting the available data in the Eth DMA buffer err = R_ETHER_Read(&this->ctrl, &rx_frame_buf, &rx_frame_dim); // DEBUG_INFO("[polling] read %08X, %u, %u", rx_frame_buf, rx_frame_dim, err); if(err != FSP_SUCCESS) { - NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(stats); - NETIF_STATS_INCREMENT_ERROR(stats, err); - NETIF_STATS_RX_TIME_AVERAGE(stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(stats); + // NETIF_STATS_INCREMENT_ERROR(stats, err); + // NETIF_STATS_RX_TIME_AVERAGE(stats); // Error, discarding the buffer without consuming it @@ -192,8 +192,8 @@ void EthernetC33Driver::poll() { this->consumed = false; // this indicates that the buffer had been consumed and the new buffer is allocated } err = R_ETHER_RxBufferUpdate(&ctrl, new_buffer); - NETIF_STATS_INCREMENT_ERROR(stats, err); - NETIF_STATS_RX_TIME_AVERAGE(stats); + // NETIF_STATS_INCREMENT_ERROR(stats, err); + // NETIF_STATS_RX_TIME_AVERAGE(stats); if(err != FSP_SUCCESS) { // DEBUG_INFO("%u", err); // FIXME handle this } From f5633d6728a04326f4f8d12bcaa2c3c0a6d86603 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:27:27 +0100 Subject: [PATCH 13/79] defined network interface abstrac class --- libraries/NetworkAPI/src/interface.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libraries/NetworkAPI/src/interface.h b/libraries/NetworkAPI/src/interface.h index 7b9637ef..7cf72e92 100644 --- a/libraries/NetworkAPI/src/interface.h +++ b/libraries/NetworkAPI/src/interface.h @@ -1 +1,14 @@ -#pragma once \ No newline at end of file +#pragma once + +/* + * The following class represent a generic network interface independently of the + * Network engine that is working on top of. + */ +class NetworkInterface { +public: + virtual ~NetworkInterface() {}; + virtual int begin(const IPAddress &ip = INADDR_NONE, const IPAddress &nm = INADDR_NONE, const IPAddress &gw = INADDR_NONE) = 0; + virtual void task() = 0; + virtual void up() = 0; + virtual void down() = 0; +}; \ No newline at end of file From 40772d1c9438dfb9bdd948132fb5c1d3dc1b4f15 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:28:05 +0100 Subject: [PATCH 14/79] fixing lwipClient --- libraries/lwIpWrapper/src/lwipClient.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.h b/libraries/lwIpWrapper/src/lwipClient.h index b087122f..d0d4e569 100644 --- a/libraries/lwIpWrapper/src/lwipClient.h +++ b/libraries/lwIpWrapper/src/lwipClient.h @@ -4,22 +4,23 @@ #include #include -class lwipClient : public Client { +// TODO improve documentation +class lwipClient : public arduino::Client { public: lwipClient(); lwipClient(uint8_t sock); - lwipClient(struct tcp_struct* tcpClient); // FIXME this should be a private constructor, friend of Server + lwipClient(struct tcp_pcb* tcpClient); // FIXME this should be a private constructor, friend of Server // disable copy constructor - LWIPTCPClient(const LWIPTCPClient&) = delete; - void operator=(const LWIPTCPClient&) = delete; + lwipClient(const lwipClient&) = delete; + void operator=(const lwipClient&) = delete; // keep move constructor - LWIPTCPClient(LWIPTCPClient&&); - void operator=(LWIPTCPClient&&); + lwipClient(lwipClient&&); + void operator=(lwipClient&&); - virtual ~LWIPTCPClient(); + virtual ~lwipClient(); virtual uint8_t status(); virtual int connect(IPAddress ip, uint16_t port); @@ -54,13 +55,13 @@ class lwipClient : public Client { uint8_t getSocketNumber(); virtual uint16_t localPort() { - return (_tcp_client->pcb->local_port); + return (this->pcb->local_port); }; virtual IPAddress remoteIP() { - return (IPAddress(_tcp_client->pcb->remote_ip.addr)); + return (IPAddress(this->pcb->remote_ip.addr)); }; virtual uint16_t remotePort() { - return (_tcp_client->pcb->remote_port); + return (this->pcb->remote_port); }; void setConnectionTimeout(uint16_t timeout) { _timeout = timeout; From cef42dafae7f36661a802d5d434638db8164ea5d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:28:36 +0100 Subject: [PATCH 15/79] fixing imports and variable names --- libraries/lwIpWrapper/src/lwipClient.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index c22237e2..91919e99 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -5,7 +5,8 @@ extern "C" { #include "Arduino.h" #include "lwipClient.h" - +#include "CNetIf.h" +#include "utils.h" // FIXME understand hos to syncronize the interrupt thread and "userspace" // TODO look into tcp_bind_netif for Ethernet and WiFiClient classes // TODO generalize the functions for extracting and inserting data into pbufs, they may be reused in UDP @@ -203,7 +204,7 @@ size_t lwipClient::write(uint8_t b) { return write(&b, 1); } -size_t lwipClient::write(const uint8_t* buf, size_t size) { +size_t lwipClient::write(const uint8_t* buffer, size_t size) { arduino::lock(); uint8_t* buffer_cursor = (uint8_t*)buffer; @@ -244,23 +245,23 @@ int lwipClient::read() { return res == 1 ? c : res; } -int lwipClient::read(uint8_t* buf, size_t size) { - if(buffer_size==0 || buffer==nullptr || this->pbuf_head==nullptr) { +int lwipClient::read(uint8_t* buffer, size_t size) { + if(size==0 || buffer==nullptr || this->pbuf_head==nullptr) { return 0; // TODO extend checks } // copy data from the lwip buffer to the app provided buffer // TODO look into pbuf_get_contiguous(this->pbuf_head, buffer_cursor, len); - // pbuf_get_contiguous: returns the pointer to the payload if buffer_size <= pbuf.len + // pbuf_get_contiguous: returns the pointer to the payload if size <= pbuf.len // otherwise copies data in the user provided buffer. This can be used in a callback paradigm, // in order to avoid memcpy data /* - * a chain of pbuf is not granted to have a size multiple of buffer_size length + * a chain of pbuf is not granted to have a size multiple of size length * meaning that across different calls of this function a pbuf could be partially copied * we need to account that */ arduino::lock(); - uint16_t copied = pbuf_copy_partial(this->pbuf_head, buffer, buffer_size, this->pbuf_offset); + uint16_t copied = pbuf_copy_partial(this->pbuf_head, buffer, size, this->pbuf_offset); this->free_pbuf_chain(copied); // __enable_irq(); From e76ded75295b7938c5d415f95b8e7db80a74be40 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:29:18 +0100 Subject: [PATCH 16/79] cleaning CNetIf classes definition --- libraries/lwIpWrapper/src/CNetIf.h | 158 ++++++++++++++++------------- 1 file changed, 88 insertions(+), 70 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index c3dd913d..9dafca0d 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -1,5 +1,4 @@ -#ifndef _ARDUINO_LWIP_NETIF_H_ -#define _ARDUINO_LWIP_NETIF_H_ +#pragma once // #define LWIP_USE_TIMER #define UNUSED(x) (void)(x) @@ -12,6 +11,8 @@ #include "IPAddress.h" #include "EthernetDriver.h" #include +#include + #ifdef USE_LWIP_AS_LIBRARY #include "lwip/include/lwip/dhcp.h" #include "lwip/include/lwip/dns.h" @@ -27,7 +28,7 @@ #include "lwIP_Arduino.h" #endif -#define LWIP_USE_TIMER +// #define LWIP_USE_TIMER #ifdef LWIP_USE_TIMER #include "FspTimer.h" @@ -95,32 +96,18 @@ typedef enum { #define TRUNCATED -3 #define INVALID_RESPONSE -4 - -ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr); - -uint32_t ip_addr_to_u32(ip_addr_t* ipaddr); +class CLwipIf; /* Base class implements DHCP, derived class will switch it on or off */ -class CNetIf { -protected: - struct netif ni; - -#ifdef LWIP_DHCP - bool dhcp_acquired; -#endif - - // IPAddress _dnsServerAddress; - - // Driver interface pointer - NetworkDriver *driver = nullptr; +class CNetIf: public NetworkInterface { public: - CNetIf(); - virtual ~CNetIf(); + CNetIf(NetworkDriver *driver=nullptr); + virtual ~CNetIf() {} /* * The begin function is called by the user in the sketch to initialize the network interface * that he is planning on using in the sketch. */ - virtual void begin( + virtual int begin( const IPAddress &ip = INADDR_NONE, const IPAddress &nm = INADDR_NONE, const IPAddress &gw = INADDR_NONE); @@ -162,46 +149,72 @@ class CNetIf { uint32_t getNmAdd() { return ip4_addr_get_u32(&(ni.netmask)); } uint32_t getGwAdd() { return ip4_addr_get_u32(&(ni.gw)); } - void setHostname(const char* name) - { - memset(hostname, 0x00, MAX_HOSTNAME_DIM); - memcpy(hostname, name, strlen(name) < MAX_HOSTNAME_DIM ? strlen(name) : MAX_HOSTNAME_DIM); - } + // void setHostname(const char* name) + // { + // memset(hostname, 0x00, MAX_HOSTNAME_DIM); + // memcpy(hostname, name, strlen(name) < MAX_HOSTNAME_DIM ? strlen(name) : MAX_HOSTNAME_DIM); + // } virtual int getMacAddress(uint8_t* mac) = 0; -}; -/* -------------------------------------------------------------------------- */ -class CEth : public CNetIf { - /* -------------------------------------------------------------------------- */ + friend CLwipIf; protected: + struct netif ni; + +#ifdef LWIP_DHCP + bool dhcp_acquired; +#endif + /* * this function is used to initialize the netif structure of lwip */ - static err_t init(struct netif* ni) override; + virtual err_t init(struct netif* ni) = 0; /* * This function is passed to lwip and used to send a buffer to the driver in order to transmit it */ - static err_t output(struct netif* ni, struct pbuf* p) override; - static const char eth_ifname_prefix = 'e'; - static uint8_t eth_id; + virtual err_t output(struct netif* ni, struct pbuf* p) = 0; + + // the following functions are used to call init and output from lwip in the object context in the C code + friend err_t _netif_init(struct netif* ni); + friend err_t _netif_output(struct netif* ni, struct pbuf* p); + + // IPAddress _dnsServerAddress; + + // Driver interface pointer + NetworkDriver *driver = nullptr; + + void linkDownCallback(); + void linkUpCallback(); +}; + +class CEth : public CNetIf { public: - CEth(); - virtual ~CEth(); - virtual void begin( + CEth(NetworkDriver *driver=nullptr); + // virtual ~CEth(); + virtual int begin( const IPAddress &ip = INADDR_NONE, const IPAddress &nm = INADDR_NONE, const IPAddress &gw = INADDR_NONE) override; - virtual void task() override; - virtual int getMacAddress(uint8_t* mac) override { UNUSED(mac); // FIXME not implemented return 1; } +protected: + /* + * this function is used to initialize the netif structure of lwip + */ + err_t init(struct netif* ni) override; + + /* + * This function is passed to lwip and used to send a buffer to the driver in order to transmit it + */ + err_t output(struct netif* ni, struct pbuf* p) override; + static const char eth_ifname_prefix = 'e'; + static uint8_t eth_id; private: /* * This function is passed to the driver class and it is meant to @@ -210,28 +223,11 @@ class CEth : public CNetIf { void consume_callback(uint8_t* buffer, uint32_t len); }; -/* -------------------------------------------------------------------------- */ class CWifiStation : public CNetIf { - /* -------------------------------------------------------------------------- */ -protected: - static const char wifistation_ifname_prefix = 'w'; - static uint8_t wifistation_id; - - /* - * this function is used to initialize the netif structure of lwip - */ - static err_t init(struct netif* ni) override; - - /* - * This function is passed to lwip and used to send a buffer to the driver in order to transmit it - */ - static err_t output(struct netif* ni, struct pbuf* p) override; - - WifiApCfg_t access_point_cfg; public: CWifiStation(); virtual ~CWifiStation(); - virtual void begin( + virtual int begin( const IPAddress &ip = INADDR_NONE, const IPAddress &nm = INADDR_NONE, const IPAddress &gw = INADDR_NONE) override; @@ -248,40 +244,62 @@ class CWifiStation : public CNetIf { virtual uint8_t* getBSSID(uint8_t* bssid); virtual int32_t getRSSI(); virtual uint8_t getEncryptionType(); -}; - -/* -------------------------------------------------------------------------- */ -class CWifiSoftAp : public CNetIf { - /* -------------------------------------------------------------------------- */ protected: static const char wifistation_ifname_prefix = 'w'; static uint8_t wifistation_id; + /* * this function is used to initialize the netif structure of lwip */ - static err_t init(struct netif* ni); + err_t init(struct netif* ni) override; /* * This function is passed to lwip and used to send a buffer to the driver in order to transmit it */ - static err_t output(struct netif* ni, struct pbuf* p); + err_t output(struct netif* ni, struct pbuf* p) override; - SoftApCfg_t soft_ap_cfg; +private: + std::vector access_points; + WifiApCfg_t access_point_cfg; + bool hw_init; // TODO this should be moved to the wifi driver class +}; + +class CWifiSoftAp : public CNetIf { public: CWifiSoftAp(); virtual ~CWifiSoftAp(); - virtual void begin( + virtual int begin( const IPAddress &ip = INADDR_NONE, const IPAddress &nm = INADDR_NONE, const IPAddress &gw = INADDR_NONE) override; virtual void task() override; + int startSoftAp(const char* ssid, const char* passphrase=nullptr, uint8_t channel=0); + int stopSoftAp(); + virtual int getMacAddress(uint8_t* mac) override; virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); virtual int32_t getRSSI(); virtual uint8_t getEncryptionType(); +protected: + static const char softap_ifname_prefix = 's'; + static uint8_t softap_id; + /* + * this function is used to initialize the netif structure of lwip + */ + err_t init(struct netif* ni); + + /* + * This function is passed to lwip and used to send a buffer to the driver in order to transmit it + */ + err_t output(struct netif* ni, struct pbuf* p); + +private: + std::vector access_points; + SoftApCfg_t soft_ap_cfg; + bool hw_init; // TODO this should be moved to the wifi driver class }; class CLwipIf { @@ -307,6 +325,7 @@ class CLwipIf { // function for setting an iface as default void setDefaultIface(CNetIf* iface); + // TODO get iface method // functions that handle DNS resolution // DNS servers are also set by dhcp @@ -321,6 +340,7 @@ class CLwipIf { #endif private: CLwipIf(); + ~CLwipIf(); // TODO define a Timer for calling tasks @@ -333,9 +353,7 @@ class CLwipIf { friend class CNetIf; -#ifdef NETWORKSTACK_USE_TIMER +#ifdef LWIP_USE_TIMER FspTimer timer; #endif }; - -#endif From d39a90ae1f20f8b32f64336460bc2b3fa718f15b Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:30:11 +0100 Subject: [PATCH 17/79] fixing class implementation and making it able to compile --- libraries/lwIpWrapper/src/CNetIf.cpp | 188 +++++++++++++++------------ 1 file changed, 105 insertions(+), 83 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 86f7413e..e14ab239 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -1,5 +1,6 @@ #include "CNetIf.h" #include +#include "utils.h" // TODO make better documentation on how this works // TODO hostname should be defined at network stack level and shared among ifaces @@ -10,6 +11,8 @@ // TODO split netif definition in different files // TODO implement WIFINetworkDriver that is then being used by both Wifi station and softAP. This will allow to use both at the same time +extern "C" void dhcps_start(struct netif *netif); // TODO understand why not include + err_t _netif_init(struct netif* ni); err_t _netif_output(struct netif* ni, struct pbuf* p); @@ -17,6 +20,10 @@ err_t _netif_output(struct netif* ni, struct pbuf* p); static void _getHostByNameCBK(const char *name, const ip_addr_t *ipaddr, void *callback_arg); #endif // LWIP_DNS +#ifdef LWIP_USE_TIMER +static void timer_cb(timer_callback_args_t* arg); +#endif + // Custom Pbuf definition used to handle RX zero copy // TODO Move this in a separate file (understand if it is required) typedef struct zerocopy_pbuf { @@ -79,7 +86,7 @@ CLwipIf::CLwipIf() { initialized just once */ lwip_init(); -#ifdef NETWORKSTACK_USE_TIMER +#ifdef LWIP_USE_TIMER uint8_t type = 8; int8_t ch = FspTimer::get_available_timer(type); @@ -88,6 +95,7 @@ CLwipIf::CLwipIf() { } /* + * FIXME update this comment * NOTE Timer and buffer size * The frequency for the timer highly influences the memory requirements for the desired transfer speed * You can calculate the buffer size required to achieve that performance from the following formula: @@ -106,6 +114,14 @@ CLwipIf::CLwipIf() { #endif } +#ifdef LWIP_USE_TIMER +static void timer_cb(timer_callback_args_t* arg) { + CLwipIf* context = (CLwipIf*)arg->p_context; + + context->task(); +} +#endif + void CLwipIf::task() { for(CNetIf* iface: this->ifaces) { // FIXME is this affecting performances? iface->task(); @@ -116,18 +132,18 @@ void CLwipIf::task() { arduino::unlock(); } -void CLwipIf::setDefaultIface(CNetif* iface) { +void CLwipIf::setDefaultIface(CNetIf* iface) { // TODO check if the iface is in the vector netif_set_default(&iface->ni); } -void CLwipIf::add_iface(CNetif* iface) { +void CLwipIf::add_iface(CNetIf* iface) { // if it is the first interface set it as the default route if(this->ifaces.empty()) { netif_set_default(&iface->ni); // TODO let the user decide which is the default one -#ifdef NETWORKSTACK_USE_TIMER +#ifdef LWIP_USE_TIMER timer.setup_overflow_irq(); timer.open(); timer.start(); @@ -143,13 +159,13 @@ CLwipIf::~CLwipIf() { } -int CLwipIf::setWifiMode(WifiMode_t mode) { +// int CLwipIf::setWifiMode(WifiMode_t mode) { // TODO adapt this // CLwipIf::getInstance().startSyncRequest(); // int rv = CEspControl::getInstance().setWifiMode(mode); // CLwipIf::getInstance().restartAsyncRequest(); // return rv; -} +// } /* *************************************************************************** * DNS related functions @@ -259,10 +275,10 @@ int CLwipIf::getHostByName(const char* aHostname, std::functionstats); // TODO create a proper stats interface @@ -275,7 +291,9 @@ CNetIf::CNetIf() } } -void CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { +int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { + driver->begin(); + ip_addr_t _ip = fromArduinoIP(ip); ip_addr_t _nm = fromArduinoIP(nm); ip_addr_t _gw = fromArduinoIP(gw); @@ -290,7 +308,7 @@ void CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw ); if(_ni == nullptr) { // FIXME error if netif_add, return error - return; + return -1; } //TODO add link up and down callback and set the link @@ -307,9 +325,10 @@ void CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw // add the interface to the network stack CLwipIf::getInstance().add_iface(this); // TODO remove interface when it is needed (??) + return 0; } -void CNetif::task() { +void CNetIf::task() { #ifdef LWIP_DHCP // TODO we can add a lazy evaluated timer for this condition if dhcp_supplied_address takes too long if(!this->dhcp_acquired && dhcp_supplied_address(&this->ni)) { @@ -324,13 +343,13 @@ void CNetif::task() { err_t _netif_init(struct netif* ni) { - CNetif *iface = (CNetif*)ni->state; + CNetIf *iface = (CNetIf*)ni->state; return iface->init(ni); // This function call can be a jmp instruction } err_t _netif_output(struct netif* ni, struct pbuf* p) { - CNetif *iface = (CNetif*)ni->state; + CNetIf *iface = (CNetIf*)ni->state; return iface->output(ni, p); // This function call can be a jmp instruction } @@ -343,6 +362,14 @@ void CNetIf::down() { netif_set_down(&this->ni); } +void CNetIf::setLinkUp() { + this->up(); +} + +void CNetIf::setLinkDown() { + this->down(); +} + void CNetIf::linkUpCallback() { netif_set_link_up(&this->ni); // TODO check that this sets the interface up also } @@ -392,20 +419,22 @@ bool CNetIf::dhcpRenew() { * ########################################################################## */ uint8_t CEth::eth_id = 0; -CEth::CEth() { - CNetif::driver = &C33EthernetDriver; // FIXME driver is the pointer to C33 ethernet driver implementation - C33EthernetDriver.stats = &this->stats; +CEth::CEth(NetworkDriver *driver) +: CNetIf(driver) { + // driver.stats = &this->stats; } -void CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { +int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { // The driver needs a callback to consume the incoming buffer this->driver->setConsumeCallback( std::bind(&CEth::consume_callback, this, std::placeholders:: _1, std::placeholders::_2)); // Call the begin function on the Parent class to init the interface - CNetif::begin(ip, nm, gw); + CNetIf::begin(ip, nm, gw); netif_set_link_up(&this->ni); // TODO test that moving this here still makes ethernet work + + return 0; } @@ -442,23 +471,18 @@ err_t CEth::output(struct netif* ni, struct pbuf* p) { */ struct pbuf *q = p; do { - NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); - NETIF_STATS_TX_TIME_START(this->stats); - auto err = C33EthernetDriver.send((uint8_t*)q->payload, q->len); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); + // NETIF_STATS_TX_TIME_START(this->stats); + auto err = driver->send((uint8_t*)q->payload, q->len); if(err != 0) { - NETIF_STATS_INCREMENT_ERROR(this->stats, err); - NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_ERROR(this->stats, err); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); errval = ERR_IF; break; } - NETIF_STATS_INCREMENT_TX_BYTES(this->stats, q->len); - NETIF_STATS_TX_TIME_AVERAGE(this->stats); + // NETIF_STATS_INCREMENT_TX_BYTES(this->stats, q->len); + // NETIF_STATS_TX_TIME_AVERAGE(this->stats); q = q->next; - - // FIXME remove this, only purpose is to verify if I ever deal with a pbuf chain - // if(q!=nullptr) { - // NETIF_STATS_INCREMENT_ERROR(this->stats, 1024); - // } } while(q != nullptr && errval != ERR_OK); return errval; @@ -482,13 +506,13 @@ void CEth::consume_callback(uint8_t* buffer, uint32_t len) { err_t err = this->ni.input((struct pbuf*)p, &this->ni); if (err != ERR_OK) { - NETIF_STATS_INCREMENT_ERROR(this->stats, err); + // NETIF_STATS_INCREMENT_ERROR(this->stats, err); - NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); - NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); pbuf_free((struct pbuf*)p); } else { - NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); + // NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); } // arduino::unlock(); } @@ -504,6 +528,10 @@ CWifiStation::CWifiStation() // CLwipIf::getInstance() } +CWifiStation::~CWifiStation() { + +} + int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { // TODO This should be called only once, make it private int res = 0; int time_num = 0; @@ -531,7 +559,7 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres } res = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); - CNetif::begin(ip, nm, gw); + CNetIf::begin(ip, nm, gw); // netif_set_link_up(&this->ni); // TODO this should be set only when successfully connected to an AP exit: // arduino::unlock(); @@ -553,7 +581,6 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { // rv = -1; // FIXME set proper error code goto exit; } - this->printAps(); // find the AP with the best rssi for (uint8_t i = 0; i < access_points.size(); i++) { @@ -635,22 +662,22 @@ err_t CWifiStation::init(struct netif* ni) { err_t CWifiStation::output(struct netif* _ni, struct pbuf* p) { // FIXME set ifn - int ifn = 0; // interface number in CNetif.cpp seems to not be set anywhere + int ifn = 0; // interface number in CNetIf.cpp seems to not be set anywhere uint8_t *buf = nullptr; uint16_t size=p->tot_len; err_t errval = ERR_IF; int err = ESP_CONTROL_OK; - NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); - NETIF_STATS_TX_TIME_START(this->stats); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); + // NETIF_STATS_TX_TIME_START(this->stats); // arduino::lock(); // p may be a chain of pbufs if(p->next != nullptr) { buf = (uint8_t*) malloc(size*sizeof(uint8_t)); if(buf == nullptr) {\ - NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); - NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); errval = ERR_MEM; goto exit; } @@ -666,11 +693,11 @@ err_t CWifiStation::output(struct netif* _ni, struct pbuf* p) { if ((err = CEspControl::getInstance().sendBuffer( ESP_STA_IF, ifn, buf, size)) == ESP_CONTROL_OK) { errval = ERR_OK; - NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); - NETIF_STATS_TX_TIME_AVERAGE(this->stats); + // NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); + // NETIF_STATS_TX_TIME_AVERAGE(this->stats); } else { - NETIF_STATS_INCREMENT_ERROR(this->stats, err); - NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_ERROR(this->stats, err); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); } exit: @@ -683,7 +710,7 @@ err_t CWifiStation::output(struct netif* _ni, struct pbuf* p) { void CWifiStation::task() { // calling the base class task, in order to make thigs work - CNetif::task(); + CNetIf::task(); // TODO in order to make things easier this should be implemented inside of Wifi driver // and not override LWIPInterface method @@ -693,7 +720,7 @@ void CWifiStation::task() { uint8_t* buffer = nullptr; struct pbuf* p = nullptr; - NETIF_STATS_RX_TIME_START(this->stats); + // NETIF_STATS_RX_TIME_START(this->stats); // arduino::lock(); // TODO do not perform this when not connected to an AP if(hw_init) { @@ -707,8 +734,7 @@ void CWifiStation::task() { while(buffer != nullptr) { // FIXME this section is redundant and should be generalized toghether with CEth::consume_callback // TODO understand if this should be moved into the base class - NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); - // NETIF_STATS_RX_TIME_START(this->stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, dim, free); @@ -718,25 +744,24 @@ void CWifiStation::task() { err_t err = this->ni.input((struct pbuf*)p, &this->ni); if (err != ERR_OK) { - NETIF_STATS_INCREMENT_ERROR(this->stats, err); + // NETIF_STATS_INCREMENT_ERROR(this->stats, err); - NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); - NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); pbuf_free((struct pbuf*)p); } else { - NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); + // NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); } buffer = CEspControl::getInstance().getStationRx(if_num, dim); - // NETIF_STATS_RX_TIME_AVERAGE(this->stats); } - NETIF_STATS_RX_TIME_AVERAGE(this->stats); + // NETIF_STATS_RX_TIME_AVERAGE(this->stats); // arduino::unlock(); } -void CWifiStation::consume_callback(uint8_t* buffer, uint32_t len) { - // FIXME take what is written in task and put it in here -} +// void CWifiStation::consume_callback(uint8_t* buffer, uint32_t len) { +// // FIXME take what is written in task and put it in here +// } const char* CWifiStation::getSSID() { return (const char*)access_point_cfg.ssid; @@ -766,10 +791,6 @@ uint8_t CWifiStation::getEncryptionType() { /* ########################################################################## */ /* CWifiSoftAp NETWORK INTERFACE CLASS */ /* ########################################################################## */ - -CWifiSoftAp::CWifiSoftAp() { } -CWifiSoftAp::~CWifiSoftAp() { } - uint8_t CWifiSoftAp::softap_id = 0; // This is required for dhcp server to assign ip addresses to AP clients @@ -781,6 +802,9 @@ CWifiSoftAp::CWifiSoftAp() } +CWifiSoftAp::~CWifiSoftAp() { } + + int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { // TODO use provided ip address, instead of default ones int res = 0; int time_num = 0; @@ -806,7 +830,7 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress res = CEspControl::getInstance().setWifiMode(WIFI_MODE_AP); // netif_set_link_up(&this->ni); // TODO this should be set only when successfully connected to an AP - CNetif::begin( + CNetIf::begin( default_dhcp_server_ip, default_nm, default_dhcp_server_ip @@ -885,22 +909,22 @@ err_t CWifiSoftAp::init(struct netif* ni) { err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { // FIXME set ifn - int ifn = 0; // interface number in CNetif.cpp seems to not be set anywhere + int ifn = 0; // interface number in CNetIf.cpp seems to not be set anywhere uint8_t *buf = nullptr; uint16_t size=p->tot_len; err_t errval = ERR_IF; int err = ESP_CONTROL_OK; - NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); - NETIF_STATS_TX_TIME_START(this->stats); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); + // NETIF_STATS_TX_TIME_START(this->stats); // arduino::lock(); // p may be a chain of pbufs if(p->next != nullptr) { buf = (uint8_t*) malloc(size*sizeof(uint8_t)); if(buf == nullptr) {\ - NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); - NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); errval = ERR_MEM; goto exit; } @@ -916,11 +940,11 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { if ((err = CEspControl::getInstance().sendBuffer( ESP_AP_IF, ifn, buf, size)) == ESP_CONTROL_OK) { errval = ERR_OK; - NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); - NETIF_STATS_TX_TIME_AVERAGE(this->stats); + // NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); + // NETIF_STATS_TX_TIME_AVERAGE(this->stats); } else { - NETIF_STATS_INCREMENT_ERROR(this->stats, err); - NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_ERROR(this->stats, err); + // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); } exit: @@ -933,7 +957,7 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { void CWifiSoftAp::task() { // calling the base class task, in order to make thigs work - CNetif::task(); + CNetIf::task(); // TODO in order to make things easier this should be implemented inside of Wifi driver // and not override LWIPInterface method @@ -943,7 +967,7 @@ void CWifiSoftAp::task() { uint8_t* buffer = nullptr; struct pbuf* p = nullptr; - NETIF_STATS_RX_TIME_START(this->stats); + // NETIF_STATS_RX_TIME_START(this->stats); // arduino::lock(); // TODO do not perform this when not connected to an AP if(hw_init) { @@ -957,8 +981,7 @@ void CWifiSoftAp::task() { while(buffer != nullptr) { // FIXME this section is redundant and should be generalized toghether with CEth::consume_callback // TODO understand if this should be moved into the base class - NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); - // NETIF_STATS_RX_TIME_START(this->stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, dim, free); @@ -968,19 +991,18 @@ void CWifiSoftAp::task() { err_t err = this->ni.input((struct pbuf*)p, &this->ni); if (err != ERR_OK) { - NETIF_STATS_INCREMENT_ERROR(this->stats, err); + // NETIF_STATS_INCREMENT_ERROR(this->stats, err); - NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); - NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS(this->stats); + // NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS(this->stats); pbuf_free((struct pbuf*)p); } else { - NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); + // NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); } buffer = CEspControl::getInstance().getStationRx(if_num, dim); - // NETIF_STATS_RX_TIME_AVERAGE(this->stats); } - NETIF_STATS_RX_TIME_AVERAGE(this->stats); + // NETIF_STATS_RX_TIME_AVERAGE(this->stats); // arduino::unlock(); } From a28de2dacae81ff83c764504e4c4ba6e30479932 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:30:47 +0100 Subject: [PATCH 18/79] defined tmp utils library --- libraries/lwIpWrapper/src/utils.h | 84 +++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 libraries/lwIpWrapper/src/utils.h diff --git a/libraries/lwIpWrapper/src/utils.h b/libraries/lwIpWrapper/src/utils.h new file mode 100644 index 00000000..e4a2ac1b --- /dev/null +++ b/libraries/lwIpWrapper/src/utils.h @@ -0,0 +1,84 @@ +#pragma once +#include +#include "lwip/include/lwip/ip_addr.h" + +inline ip_addr_t fromArduinoIP(const IPAddress& ip) { +#if LWIP_IPV4 + ip_addr_t res; + if(ip.type() == arduino::IPv4) { + if(ip == INADDR_NONE) { + ip_addr_copy(res, *IP4_ADDR_ANY); + } else { + IP_ADDR4(&res, ip[0], ip[1], ip[2], ip[3]); + } + } +#endif // LWIP_IPV4 +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif // LWIP_IPV4 && LWIP_IPV6 +#if LWIP_IPV6 // TODO change the setting and try ipv6: This is currently set to 0 + if(ip.type() == arduino::IPv6) { + if(ip == INADDR_NONE) { + // ip_addr_copy(res, *IP6_ADDR_ANY); + // FIXME implement this + } else { + // FIXME implement this, it could be useful to have a function in the IPAddress class to help this out + } + } +#endif // LWIP_IPV6 + return res; +} + +inline IPAddress toArduinoIP(const ip_addr_t* ip) { + if(ip == nullptr) { + return INADDR_NONE; + } + +#if LWIP_IPV4 + if(IP_IS_V4(ip)) { + if(ip_addr_isany_val(*ip)) { + return INADDR_NONE; + } else { + return IPAddress(arduino::IPv4, (uint8_t*)&ip_2_ip4(ip)->addr); + } + } +#endif // LWIP_IPV4 + +#if LWIP_IPV6 // TODO change the setting and try ipv6: This is currently set to 0 + if(IP_IS_V6(ip)) { + if(ip_addr_isany_val(*ip)) { + return IN6ADDR_ANY; + } else { + return IPAddress(arduino::IPv6, (uint8_t*)ip_2_ip6(ip)->addr); + } + } +#endif + +#if LWIP_IPV4 && LWIP_IPV6 + if(IP_IS_ANY_TYPE_VAL(ip)) { + // FIXME understand what this means + } +#endif + + return INADDR_NONE; +} + + +namespace arduino { + // TODO leverage on RAII + inline volatile uint32_t lock_counter; + inline void lock() { + __disable_irq(); + lock_counter++; // This action breaks everything + } + + inline void unlock() { + if(lock_counter > 0) { + lock_counter--; + } + + if(lock_counter == 0) { + __enable_irq(); // this could be called multiple times if the calls are not setup properly + } + } +} \ No newline at end of file From 460a0d5c2df9929b982f9f9ef4d5d3c66da4a7a2 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:31:18 +0100 Subject: [PATCH 19/79] reimplementing wifi handle --- libraries/WiFi/src/WiFiC3.h | 267 +----------------------------------- 1 file changed, 7 insertions(+), 260 deletions(-) diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 2995cdcf..ffe55cbf 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -1,267 +1,14 @@ -#ifndef C_ARDUINO_WIFI_H -#define C_ARDUINO_WIFI_H +#pragma once #include "CNetIf.h" -#define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" - -class CWifi { -private: - void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); - unsigned long _timeout; - bool _useStaticIp = false; - CNetIf *ni; - -public: - CWifi(); - - /* - * Get firmware version - */ - static const char* firmwareVersion(); - - - /* - * Start WiFi connection for OPEN networks - * param ssid: Pointer to the SSID string. - */ - int begin(const char* ssid); - - - - /* Start WiFi connection with passphrase - * the most secure supported mode will be automatically selected - * - * param ssid: Pointer to the SSID string. - * param passphrase: Passphrase. Valid characters in a passphrase - * must be between ASCII 32-126 (decimal). - */ - int begin(const char* ssid, const char *passphrase); - - /* connect as Access Point with a standard passphrase */ - uint8_t beginAP(const char *ssid); - uint8_t beginAP(const char *ssid, uint8_t channel); - uint8_t beginAP(const char *ssid, const char* passphrase); - uint8_t beginAP(const char *ssid, const char* passphrase, uint8_t channel); - - /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - */ - void config(IPAddress local_ip); - - /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - * param dns_server: IP configuration for DNS server 1 - */ - void config(IPAddress local_ip, IPAddress dns_server); - - /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - * param dns_server: IP configuration for DNS server 1 - * param gateway : Static gateway configuration - */ - void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); - - /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - * param dns_server: IP configuration for DNS server 1 - * param gateway: Static gateway configuration - * param subnet: Static Subnet mask - */ - void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); - - /* Change DNS IP configuration - * - * param dns_server1: IP configuration for DNS server 1 - */ - void setDNS(IPAddress dns_server1); - - /* Change DNS IP configuration - * - * param dns_server1: IP configuration for DNS server 1 - * param dns_server2: IP configuration for DNS server 2 - * - */ - void setDNS(IPAddress dns_server1, IPAddress dns_server2); - - - /* Set the hostname used for DHCP requests - * - * param name: hostname to set - * - */ - void setHostname(const char* name); - - /* - * Disconnect from the network - * - * return: one value of wl_status_t enum - */ - int disconnect(void); - - void end(void); - - /* - * Get the interface MAC address. - * - * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH - * - * the value returned by this function is meaningfull only if called - * afert a begin (both begin or beginAP) or a ScanNetwork function - * otherwise an empty mac address is returned - */ - uint8_t* macAddress(uint8_t* mac); - - /* - * Get the interface IP address. - * - * return: IP address value - */ - IPAddress localIP(); - - /* - * Get the interface subnet mask address. - * - * return: subnet mask address value - */ - IPAddress subnetMask(); - - /* - * Get the gateway IP address. - * - * return: gateway IP address value - */ - IPAddress gatewayIP(); - - /* - * Get the DNS server IP address. - * - * return: DNS server IP address value - */ - IPAddress dnsIP(int n = 0); - - /* - * Return the current SSID associated with the network - * - * return: ssid string - */ - const char* SSID(); - - /* - * Return the current BSSID associated with the network. - * It is the MAC address of the Access Point - * - * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH - */ - uint8_t* BSSID(uint8_t* bssid); - - /* - * Return the current RSSI/Received Signal Strength in dBm) - * associated with the network - * - * return: signed value - */ - int32_t RSSI(); - - /* - * Return the Encryption Type associated with the network - * - * return: one value of wl_enc_type enum - */ - uint8_t encryptionType(); - - /* - * Start scan WiFi networks available - * - * return: Number of discovered networks - */ - int8_t scanNetworks(); - - /* - * Return the SSID discovered during the network scan. - * - * param networkItem: specify from which network item want to get the information - * - * return: SSID string of the specified item on the networks scanned list - */ - const char* SSID(uint8_t networkItem); - - /* - * Return the encryption type of the networks discovered during the scanNetworks - * - * param networkItem: specify from which network item want to get the information - * - * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list - - enum wl_enc_type : - ENC_TYPE_WEP, - ENC_TYPE_WPA, - ENC_TYPE_WPA2, - ENC_TYPE_WPA2_ENTERPRISE, - ENC_TYPE_WPA3, - ENC_TYPE_NONE, - ENC_TYPE_AUTO, - - ENC_TYPE_UNKNOWN = 255 - - */ - uint8_t encryptionType(uint8_t networkItem); - - uint8_t* BSSID(uint8_t networkItem, uint8_t* bssid); - uint8_t channel(uint8_t networkItem); - - /* - * Return the RSSI of the networks discovered during the scanNetworks - * - * param networkItem: specify from which network item want to get the information - * - * return: signed value of RSSI of the specified item on the networks scanned list - */ - int32_t RSSI(uint8_t networkItem); - - /* - * Return Connection status. - * - * return: one of the value defined in wl_status_t - */ - uint8_t status(); - - /* - * Return The deauthentication reason code. - * - * return: the deauthentication reason code - */ - uint8_t reasonCode(); - - /* - * Resolve the given hostname to an IP address. - * param aHostname: Name to be resolved - * param aResult: IPAddress structure to store the returned IP address - * result: 1 if aIPAddrString was successfully converted to an IP address, - * else error code - */ - int hostByName(const char* aHostname, IPAddress& aResult); - - unsigned long getTime(); - - void lowPowerMode(); - void noLowPowerMode(); - - - - void setTimeout(unsigned long timeout); - - -}; - -extern CWifi WiFi; - #include "WiFiClient.h" #include "WiFiServer.h" #include "WiFiUdp.h" -#endif +#define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" + +// TODO Instantiate the drivers for wifi with default configuration parameters + +// Instantiate a global variable from CWifiStation calling it WiFi + From ae29df794ff14baf1da8d939d58db2e79a211bc6 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 29 Dec 2023 13:34:09 +0100 Subject: [PATCH 20/79] commnting code not yet ready to be compiled --- libraries/Ethernet/src/EthernetClient.h | 2 +- libraries/lwIpWrapper/src/lwipServer.cpp | 37 ++++++++++++------------ libraries/lwIpWrapper/src/lwipUDP.cpp | 26 ++++++++--------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/libraries/Ethernet/src/EthernetClient.h b/libraries/Ethernet/src/EthernetClient.h index dbfa0012..c3b16242 100644 --- a/libraries/Ethernet/src/EthernetClient.h +++ b/libraries/Ethernet/src/EthernetClient.h @@ -7,7 +7,7 @@ class EthernetClient : public lwipClient { public: EthernetClient() {} - EthernetClient(struct tcp_struct *tcpClient) : lwipClient(tcpClient) {} + EthernetClient(struct tcp_struct *tcpClient) : lwipClient() {} // FIXME }; #endif \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipServer.cpp b/libraries/lwIpWrapper/src/lwipServer.cpp index be42b2a4..768b5887 100644 --- a/libraries/lwIpWrapper/src/lwipServer.cpp +++ b/libraries/lwIpWrapper/src/lwipServer.cpp @@ -51,11 +51,11 @@ void lwipServer::accept() /* Free client if disconnected */ for (int n = 0; n < MAX_CLIENT; n++) { if (_tcp_client[n] != NULL) { - lwipClient client(_tcp_client[n]); - if (client.status() == TCP_CLOSING) { - mem_free(_tcp_client[n]); - _tcp_client[n] = NULL; - } + // lwipClient client(_tcp_client[n]); // FIXME + // if (client.status() == TCP_CLOSING) { + // mem_free(_tcp_client[n]); + // _tcp_client[n] = NULL; + // } } } } @@ -67,19 +67,20 @@ lwipClient lwipServer::available() for (int n = 0; n < MAX_CLIENT; n++) { if (_tcp_client[n] != NULL) { if (_tcp_client[n]->pcb != NULL) { - lwipClient client(_tcp_client[n]); - uint8_t s = client.status(); - if (s == TCP_ACCEPTED) { - if (client.available()) { - return client; - } - } + // lwipClient client(_tcp_client[n]); // FIXME + // uint8_t s = client.status(); + // if (s == TCP_ACCEPTED) { + // if (client.available()) { + // return client; + // } + // } } } } struct tcp_struct* default_client = NULL; - return lwipClient(default_client); + return lwipClient(); // FIXME + // return lwipClient(default_client); } size_t lwipServer::write(uint8_t b) @@ -96,11 +97,11 @@ size_t lwipServer::write(const uint8_t* buffer, size_t size) for (int n = 0; n < MAX_CLIENT; n++) { if (_tcp_client[n] != NULL) { if (_tcp_client[n]->pcb != NULL) { - lwipClient client(_tcp_client[n]); - uint8_t s = client.status(); - if (s == TCP_ACCEPTED) { - n += client.write(buffer, size); - } + // lwipClient client(_tcp_client[n]); + // uint8_t s = client.status(); + // if (s == TCP_ACCEPTED) { + // n += client.write(buffer, size); + // } } } } diff --git a/libraries/lwIpWrapper/src/lwipUDP.cpp b/libraries/lwIpWrapper/src/lwipUDP.cpp index 0ea680f8..2e84ac26 100644 --- a/libraries/lwIpWrapper/src/lwipUDP.cpp +++ b/libraries/lwIpWrapper/src/lwipUDP.cpp @@ -64,7 +64,7 @@ uint8_t lwipUDP::begin(IPAddress ip, uint16_t port, bool multicast) ip_addr_t ipaddr; err_t err; - u8_to_ip_addr(rawIPAddress(ip), &ipaddr); + // u8_to_ip_addr(rawIPAddress(ip), &ipaddr); // FIXME if (multicast) { err = udp_bind(_udp.pcb, IP_ADDR_ANY, port); } else { @@ -86,7 +86,7 @@ uint8_t lwipUDP::begin(IPAddress ip, uint16_t port, bool multicast) _port = port; _remaining = 0; - CLwipIf::getInstance().lwip_task(); + // CLwipIf::getInstance().lwip_task(); return 1; } @@ -107,7 +107,7 @@ void lwipUDP::stop() _udp.pcb = NULL; } - CLwipIf::getInstance().lwip_task(); + // CLwipIf::getInstance().lwip_task(); } int lwipUDP::beginPacket(const char* host, uint16_t port) @@ -135,7 +135,7 @@ int lwipUDP::beginPacket(IPAddress ip, uint16_t port) _sendtoPort = port; udp_recv(_udp.pcb, &udp_receive_callback, &_udp); - CLwipIf::getInstance().lwip_task(); + // CLwipIf::getInstance().lwip_task(); return 1; } @@ -147,16 +147,16 @@ int lwipUDP::endPacket() } ip_addr_t ipaddr; - if (ERR_OK != udp_sendto(_udp.pcb, _data, u8_to_ip_addr(rawIPAddress(_sendtoIP), &ipaddr), _sendtoPort)) { - __disable_irq(); - _data = pbuffer_free_data(_data); - __enable_irq(); - return 0; - } + // if (ERR_OK != udp_sendto(_udp.pcb, _data, u8_to_ip_addr(rawIPAddress(_sendtoIP), &ipaddr), _sendtoPort)) { + // __disable_irq(); + // _data = pbuffer_free_data(_data); + // __enable_irq(); + // return 0; + // } _data = NULL; - CLwipIf::getInstance().lwip_task(); + // CLwipIf::getInstance().lwip_task(); return 1; } @@ -188,10 +188,10 @@ int lwipUDP::parsePacket() // read(); // } - CLwipIf::getInstance().lwip_task(); + // CLwipIf::getInstance().lwip_task(); if (_udp.data.available > 0) { - _remoteIP = IPAddress(ip_addr_to_u32(&(_udp.ip))); + // _remoteIP = IPAddress(ip_addr_to_u32(&(_udp.ip))); // FIXME _remotePort = _udp.port; _remaining = _udp.data.available; From 9a871ef1c6734bcf5c78bd18858a13b14f20ce74 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 2 Jan 2024 15:58:05 +0100 Subject: [PATCH 21/79] deleted lwip tcp wrapper --- libraries/lwIpWrapper/src/lwipTcp.cpp | 231 -------------------------- libraries/lwIpWrapper/src/lwipTcp.h | 16 -- 2 files changed, 247 deletions(-) delete mode 100644 libraries/lwIpWrapper/src/lwipTcp.cpp delete mode 100644 libraries/lwIpWrapper/src/lwipTcp.h diff --git a/libraries/lwIpWrapper/src/lwipTcp.cpp b/libraries/lwIpWrapper/src/lwipTcp.cpp deleted file mode 100644 index 68026279..00000000 --- a/libraries/lwIpWrapper/src/lwipTcp.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "lwipTcp.h" - -#if LWIP_TCP -static err_t tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err); -static err_t tcp_sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len); -static void tcp_err_callback(void* arg, err_t err); -/** - * @brief Function called when TCP connection established - * @param arg: user supplied argument - * @param tpcb: pointer on the connection control block - * @param err: when connection correctly established err should be ERR_OK - * @retval err_t: returned error - */ -err_t tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err) -{ - struct tcp_struct* tcp_arg = (struct tcp_struct*)arg; - - if (err == ERR_OK) { - if ((tcp_arg != NULL) && (tcp_arg->pcb == tpcb)) { - tcp_arg->state = TCP_CONNECTED; - - /* initialize LwIP tcp_recv callback function */ - tcp_recv(tpcb, tcp_recv_callback); - - /* initialize LwIP tcp_sent callback function */ - tcp_sent(tpcb, tcp_sent_callback); - - /* initialize LwIP tcp_err callback function */ - tcp_err(tpcb, tcp_err_callback); - - return ERR_OK; - } else { - /* close connection */ - tcp_connection_close(tpcb, tcp_arg); - - return ERR_ARG; - } - } else { - /* close connection */ - tcp_connection_close(tpcb, tcp_arg); - } - return err; -} - -/** - * @brief This function is the implementation of tcp_accept LwIP callback - * @param arg user supplied argument - * @param newpcb: pointer on tcp_pcb struct for the newly created tcp connection - * @param err: when connection correctly established err should be ERR_OK - * @retval err_t: error status - */ -err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err) -{ - err_t ret_err; - uint8_t accepted; - struct tcp_struct** tcpClient = (struct tcp_struct**)arg; - - /* set priority for the newly accepted tcp connection newpcb */ - tcp_setprio(newpcb, TCP_PRIO_MIN); - - if ((tcpClient != NULL) && (ERR_OK == err)) { - struct tcp_struct* client = (struct tcp_struct*)mem_malloc(sizeof(struct tcp_struct)); - - if (client != NULL) { - client->state = TCP_ACCEPTED; - client->pcb = newpcb; - client->data.p = NULL; - client->data.available = 0; - - /* Looking for an empty socket */ - for (uint16_t i = 0; i < MAX_CLIENT; i++) { - if (tcpClient[i] == NULL) { - tcpClient[i] = client; - accepted = 1; - break; - } - } - - if (accepted) { - /* pass newly allocated client structure as argument to newpcb */ - tcp_arg(newpcb, client); - - /* initialize lwip tcp_recv callback function for newpcb */ - tcp_recv(newpcb, tcp_recv_callback); - - /* initialize lwip tcp_err callback function for newpcb */ - tcp_err(newpcb, tcp_err_callback); - - /* initialize LwIP tcp_sent callback function */ - tcp_sent(newpcb, tcp_sent_callback); - - ret_err = ERR_OK; - } else { - /* close tcp connection */ - tcp_connection_close(newpcb, client); - mem_free(client); - - /* return memory error */ - ret_err = ERR_MEM; - } - } else { - /* close tcp connection */ - tcp_connection_close(newpcb, client); - mem_free(client); - - /* return memory error */ - ret_err = ERR_MEM; - } - } else { - tcp_close(newpcb); - ret_err = ERR_ARG; - } - return ret_err; -} - -/** - * @brief tcp_receiv callback - * @param arg: argument to be passed to receive callback - * @param tpcb: tcp connection control block - * @param err: receive error code - * @retval err_t: returned error - */ -static err_t tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err) -{ - struct tcp_struct* tcp_arg = (struct tcp_struct*)arg; - err_t ret_err; - - /* if we receive an empty tcp frame from server => close connection */ - if (p == NULL) { - /* we're done sending, close connection */ - tcp_connection_close(tpcb, tcp_arg); - ret_err = ERR_OK; - } - /* else : a non empty frame was received from echo server but for some reason err != ERR_OK */ - else if (err != ERR_OK) { - /* free received pbuf*/ - if (p != NULL) { - pbuf_free(p); - } - ret_err = err; - } else if ((tcp_arg->state == TCP_CONNECTED) || (tcp_arg->state == TCP_ACCEPTED)) { - /* Acknowledge data reception */ - tcp_recved(tpcb, p->tot_len); - - if (tcp_arg->data.p == NULL) { - tcp_arg->data.p = p; - } else { - pbuf_chain(tcp_arg->data.p, p); - } - - tcp_arg->data.available += p->len; - ret_err = ERR_OK; - } - /* data received when connection already closed */ - else { - /* Acknowledge data reception */ - tcp_recved(tpcb, p->tot_len); - - /* free pbuf and do nothing */ - pbuf_free(p); - ret_err = ERR_OK; - } - return ret_err; -} - -/** - * @brief This function implements the tcp_sent LwIP callback (called when ACK - * is received from remote host for sent data) - * @param arg: pointer on argument passed to callback - * @param tcp_pcb: tcp connection control block - * @param len: length of data sent - * @retval err_t: returned error code - */ -static err_t tcp_sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len) -{ - struct tcp_struct* tcp_arg = (struct tcp_struct*)arg; - - LWIP_UNUSED_ARG(len); - - if ((tcp_arg != NULL) && (tcp_arg->pcb == tpcb)) { - return ERR_OK; - } - - return ERR_ARG; -} - -/** Function prototype for tcp error callback functions. Called when the pcb - * receives a RST or is unexpectedly closed for any other reason. - * - * @note The corresponding pcb is already freed when this callback is called! - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param err Error code to indicate why the pcb has been closed - * ERR_ABRT: aborted through tcp_abort or by a TCP timer - * ERR_RST: the connection was reset by the remote host - */ -static void tcp_err_callback(void* arg, err_t err) -{ - struct tcp_struct* tcp_arg = (struct tcp_struct*)arg; - - if (tcp_arg != NULL) { - if (ERR_OK != err) { - tcp_arg->pcb = NULL; - tcp_arg->state = TCP_CLOSING; - } - } -} - -/** - * @brief This function is used to close the tcp connection with server - * @param tpcb: tcp connection control block - * @param es: pointer on echoclient structure - * @retval None - */ -void tcp_connection_close(struct tcp_pcb* tpcb, struct tcp_struct* tcp) -{ - /* remove callbacks */ - tcp_recv(tpcb, NULL); - tcp_sent(tpcb, NULL); - tcp_poll(tpcb, NULL, 0); - tcp_err(tpcb, NULL); - tcp_accept(tpcb, NULL); - - /* close tcp connection */ - tcp_close(tpcb); - - tcp->pcb = NULL; - tcp->state = TCP_CLOSING; -} - -#endif /* LWIP_TCP */ diff --git a/libraries/lwIpWrapper/src/lwipTcp.h b/libraries/lwIpWrapper/src/lwipTcp.h deleted file mode 100644 index 3c4e689b..00000000 --- a/libraries/lwIpWrapper/src/lwipTcp.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ARDUINO_LWIP_IF_TCP_HELPERS_H -#define _ARDUINO_LWIP_IF_TCP_HELPERS_H - -#include "CNetIf.h" -#include "lwipTypes.h" - -#if LWIP_TCP -err_t tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err); -err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err); -void tcp_connection_close(struct tcp_pcb* tpcb, struct tcp_struct* tcp); - -#else -#error "LWIP_TCP must be enabled in lwipopts.h" -#endif - -#endif \ No newline at end of file From 0b6dd35ce1264250d54ad10a47df7a473adbbb81 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 2 Jan 2024 16:07:43 +0100 Subject: [PATCH 22/79] implemented netowrk interfaces specific clients --- libraries/Ethernet/src/EthernetClient.h | 10 +++++++--- libraries/WiFi/src/WiFiClient.h | 8 ++++++-- libraries/lwIpWrapper/src/CNetIf.h | 8 ++++++-- libraries/lwIpWrapper/src/lwipClient.h | 7 ++++++- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libraries/Ethernet/src/EthernetClient.h b/libraries/Ethernet/src/EthernetClient.h index c3b16242..7bb5cca2 100644 --- a/libraries/Ethernet/src/EthernetClient.h +++ b/libraries/Ethernet/src/EthernetClient.h @@ -5,9 +5,13 @@ #include "lwipClient.h" class EthernetClient : public lwipClient { - public: - EthernetClient() {} - EthernetClient(struct tcp_struct *tcpClient) : lwipClient() {} // FIXME +public: + EthernetClient() { + this->bindCNetIf(Ethernet); + } + EthernetClient(struct tcp_pcb *pcb) : lwipClient(pcb) { + this->bindCNetIf(Ethernet); + } }; #endif \ No newline at end of file diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index 19c7e83d..e6f26fd6 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -6,8 +6,12 @@ class WiFiClient : public lwipClient { public: - WiFiClient() {} - WiFiClient(struct tcp_struct *tcpClient) : lwipClient(tcpClient) {} + WiFiClient() { + this->bindCNetIf(WiFi); + } + WiFiClient(struct tcp_pcb *pcb) : lwipClient(pcb) { + this->bindCNetIf(WiFi); + } }; #endif diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 9dafca0d..8fd96445 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -97,6 +97,7 @@ typedef enum { #define INVALID_RESPONSE -4 class CLwipIf; +class lwipClient; /* Base class implements DHCP, derived class will switch it on or off */ class CNetIf: public NetworkInterface { @@ -238,7 +239,7 @@ class CWifiStation : public CNetIf { virtual void task() override; - virtual int getMacAddress(uint8_t* mac) override; + virtual int getMacAddress(uint8_t* mac) override {} virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); @@ -277,7 +278,7 @@ class CWifiSoftAp : public CNetIf { int startSoftAp(const char* ssid, const char* passphrase=nullptr, uint8_t channel=0); int stopSoftAp(); - virtual int getMacAddress(uint8_t* mac) override; + virtual int getMacAddress(uint8_t* mac) override {} virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); @@ -357,3 +358,6 @@ class CLwipIf { FspTimer timer; #endif }; + +extern CEth Ethernet; +extern CWifiStation WiFi; \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipClient.h b/libraries/lwIpWrapper/src/lwipClient.h index d0d4e569..5188f42e 100644 --- a/libraries/lwIpWrapper/src/lwipClient.h +++ b/libraries/lwIpWrapper/src/lwipClient.h @@ -3,6 +3,7 @@ #include #include #include +#include "CNetIf.h" // TODO improve documentation @@ -67,6 +68,10 @@ class lwipClient : public arduino::Client { _timeout = timeout; } + void bindCNetIf(CNetIf &n) { + tcp_bind_netif(this->pcb, n.getNi()); + } + friend class lwipServer; using Print::write; @@ -82,7 +87,7 @@ class lwipClient : public arduino::Client { // TCP related info of the socket _tcp_state_t state = TCP_NONE; struct pbuf* pbuf_head = nullptr; - struct tcp_pcb* pcb = nullptr; + struct tcp_pcb* pcb = nullptr; uint16_t pbuf_offset = 0; uint16_t _timeout = 10000; From f911f6711ae3e1f931613128f8fe8c89bb23a1fb Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 2 Jan 2024 16:08:43 +0100 Subject: [PATCH 23/79] defined Wifi global variable for network interface --- libraries/WiFi/src/WiFi.cpp | 620 ++++++++++++++++++------------------ libraries/WiFi/src/WiFiC3.h | 4 + 2 files changed, 314 insertions(+), 310 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 59e742a0..d91a212e 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -1,331 +1,331 @@ #include "WiFiC3.h" -extern "C" void dhcps_start(struct netif *netif); +// extern "C" void dhcps_start(struct netif *netif); -/* -------------------------------------------------------------------------- */ -CWifi::CWifi() : _timeout(50000), ni(nullptr) { -} -/* -------------------------------------------------------------------------- */ +// /* -------------------------------------------------------------------------- */ +// CWifi::CWifi() : _timeout(50000), ni(nullptr) { +// } +// /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -const char* CWifi::firmwareVersion() { -/* -------------------------------------------------------------------------- */ - /* silly "dummy" implementation to keep compatibility, at the present - the WiFi fw does not return any version number */ - return WIFI_FIRMWARE_LATEST_VERSION; -} +// /* -------------------------------------------------------------------------- */ +// const char* CWifi::firmwareVersion() { +// /* -------------------------------------------------------------------------- */ +// /* silly "dummy" implementation to keep compatibility, at the present +// the WiFi fw does not return any version number */ +// return WIFI_FIRMWARE_LATEST_VERSION; +// } -/* -------------------------------------------------------------------------- */ -int CWifi::begin(const char* ssid) { -/* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); - CLwipIf::getInstance().connectToAp(ssid, nullptr); - if(ni != nullptr && !_useStaticIp) { - ni->DhcpStart(); - } +// /* -------------------------------------------------------------------------- */ +// int CWifi::begin(const char* ssid) { +// /* -------------------------------------------------------------------------- */ +// ni = CLwipIf::getInstance().get(NI_WIFI_STATION); +// CLwipIf::getInstance().connectToAp(ssid, nullptr); +// if(ni != nullptr && !_useStaticIp) { +// ni->DhcpStart(); +// } - return CLwipIf::getInstance().getWifiStatus(); -} +// return CLwipIf::getInstance().getWifiStatus(); +// } -/* -------------------------------------------------------------------------- */ -int CWifi::begin(const char* ssid, const char *passphrase) { -/* -------------------------------------------------------------------------- */ +// /* -------------------------------------------------------------------------- */ +// int CWifi::begin(const char* ssid, const char *passphrase) { +// /* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); - CLwipIf::getInstance().connectToAp(ssid, passphrase); - if(ni != nullptr && !_useStaticIp) { - ni->DhcpStart(); - } +// ni = CLwipIf::getInstance().get(NI_WIFI_STATION); +// CLwipIf::getInstance().connectToAp(ssid, passphrase); +// if(ni != nullptr && !_useStaticIp) { +// ni->DhcpStart(); +// } - return CLwipIf::getInstance().getWifiStatus(); -} - -/* passphrase is needed so a default one will be set */ -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::beginAP(const char *ssid) { -/* -------------------------------------------------------------------------- */ - return beginAP(ssid,1); -} - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::beginAP(const char *ssid, uint8_t channel) { -/* -------------------------------------------------------------------------- */ - return beginAP(ssid,nullptr,channel); -} - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { -/* -------------------------------------------------------------------------- */ - return beginAP(ssid,passphrase,1); -} - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { -/* -------------------------------------------------------------------------- */ +// return CLwipIf::getInstance().getWifiStatus(); +// } + +// /* passphrase is needed so a default one will be set */ +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::beginAP(const char *ssid) { +// /* -------------------------------------------------------------------------- */ +// return beginAP(ssid,1); +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::beginAP(const char *ssid, uint8_t channel) { +// /* -------------------------------------------------------------------------- */ +// return beginAP(ssid,nullptr,channel); +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { +// /* -------------------------------------------------------------------------- */ +// return beginAP(ssid,passphrase,1); +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { +// /* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); - CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); - if(ni != nullptr) { +// ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); +// CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); +// if(ni != nullptr) { - dhcps_start(ni->getNi()); - } +// dhcps_start(ni->getNi()); +// } - return CLwipIf::getInstance().getWifiStatus(); -} - - - -/* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip) { -/* -------------------------------------------------------------------------- */ - IPAddress _nm(255, 255, 255, 0); - IPAddress _gw = local_ip; - _gw[3] = 1; - - _config(local_ip, _gw, _nm); -} - -extern uint8_t *IpAddress2uint8(IPAddress a); - -/* -------------------------------------------------------------------------- */ -void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { -/* -------------------------------------------------------------------------- */ - _useStaticIp = local_ip != INADDR_NONE; - if(ni != nullptr) { - ni->DhcpStop(); - ni->DhcpNotUsed(); - IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); - IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); - IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); - } - else { - CNetIf::default_ip = local_ip; - CNetIf::default_nm = subnet; - CNetIf::default_gw = gateway; - CNetIf::default_dhcp_server_ip = local_ip; - } -} - -/* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip, IPAddress dns_server) { -/* -------------------------------------------------------------------------- */ - config(local_ip); - CLwipIf::getInstance().addDns(dns_server); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { -/* -------------------------------------------------------------------------- */ - IPAddress _nm(255, 255, 255, 0); - _config(local_ip, gateway, _nm); - CLwipIf::getInstance().addDns(dns_server); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { -/* -------------------------------------------------------------------------- */ - _config(local_ip, gateway, subnet); - CLwipIf::getInstance().addDns(dns_server); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::setDNS(IPAddress dns_server1) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server1); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server1); - CLwipIf::getInstance().addDns(dns_server2); +// return CLwipIf::getInstance().getWifiStatus(); +// } + + + +// /* -------------------------------------------------------------------------- */ +// void CWifi::config(IPAddress local_ip) { +// /* -------------------------------------------------------------------------- */ +// IPAddress _nm(255, 255, 255, 0); +// IPAddress _gw = local_ip; +// _gw[3] = 1; + +// _config(local_ip, _gw, _nm); +// } + +// extern uint8_t *IpAddress2uint8(IPAddress a); + +// /* -------------------------------------------------------------------------- */ +// void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { +// /* -------------------------------------------------------------------------- */ +// _useStaticIp = local_ip != INADDR_NONE; +// if(ni != nullptr) { +// ni->DhcpStop(); +// ni->DhcpNotUsed(); +// IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); +// IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); +// IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); +// } +// else { +// CNetIf::default_ip = local_ip; +// CNetIf::default_nm = subnet; +// CNetIf::default_gw = gateway; +// CNetIf::default_dhcp_server_ip = local_ip; +// } +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::config(IPAddress local_ip, IPAddress dns_server) { +// /* -------------------------------------------------------------------------- */ +// config(local_ip); +// CLwipIf::getInstance().addDns(dns_server); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { +// /* -------------------------------------------------------------------------- */ +// IPAddress _nm(255, 255, 255, 0); +// _config(local_ip, gateway, _nm); +// CLwipIf::getInstance().addDns(dns_server); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { +// /* -------------------------------------------------------------------------- */ +// _config(local_ip, gateway, subnet); +// CLwipIf::getInstance().addDns(dns_server); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::setDNS(IPAddress dns_server1) { +// /* -------------------------------------------------------------------------- */ +// CLwipIf::getInstance().addDns(dns_server1); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { +// /* -------------------------------------------------------------------------- */ +// CLwipIf::getInstance().addDns(dns_server1); +// CLwipIf::getInstance().addDns(dns_server2); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::setHostname(const char* name) { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - ni->setHostname(name); - } -} - -/* -------------------------------------------------------------------------- */ -int CWifi::disconnect() { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().disconnectFromAp(); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::end(void) { -/* -------------------------------------------------------------------------- */ - -} - -/* -------------------------------------------------------------------------- */ -uint8_t* CWifi::macAddress(uint8_t* mac) { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { - return mac; - } - } - memset(mac,0x00,6); - return mac; -} - -/* -------------------------------------------------------------------------- */ -int8_t CWifi::scanNetworks() { -/* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); - if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { - return CLwipIf::getInstance().getApNum(); - } - return 0; -} +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::setHostname(const char* name) { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// ni->setHostname(name); +// } +// } + +// /* -------------------------------------------------------------------------- */ +// int CWifi::disconnect() { +// /* -------------------------------------------------------------------------- */ +// CLwipIf::getInstance().disconnectFromAp(); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::end(void) { +// /* -------------------------------------------------------------------------- */ + +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t* CWifi::macAddress(uint8_t* mac) { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { +// return mac; +// } +// } +// memset(mac,0x00,6); +// return mac; +// } + +// /* -------------------------------------------------------------------------- */ +// int8_t CWifi::scanNetworks() { +// /* -------------------------------------------------------------------------- */ +// ni = CLwipIf::getInstance().get(NI_WIFI_STATION); +// if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { +// return CLwipIf::getInstance().getApNum(); +// } +// return 0; +// } -/* -------------------------------------------------------------------------- */ -IPAddress CWifi::localIP() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getIpAdd()); - } - return IPAddress((uint32_t)0); -} - -/* -------------------------------------------------------------------------- */ -IPAddress CWifi::subnetMask() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getNmAdd()); - } - return IPAddress((uint32_t)0); -} - -/* -------------------------------------------------------------------------- */ -IPAddress CWifi::gatewayIP() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getGwAdd()); - } - return IPAddress((uint32_t)0); -} - -/* -------------------------------------------------------------------------- */ -IPAddress CWifi::dnsIP(int n) { - return CLwipIf::getInstance().getDns(n); -} - -/* -------------------------------------------------------------------------- */ -const char* CWifi::SSID(uint8_t networkItem) { - return CLwipIf::getInstance().getSSID(networkItem); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -int32_t CWifi::RSSI(uint8_t networkItem) { - return CLwipIf::getInstance().getRSSI(networkItem); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::encryptionType(uint8_t networkItem) { - return CLwipIf::getInstance().getEncrType(networkItem); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { - return CLwipIf::getInstance().getBSSID(networkItem,bssid); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::channel(uint8_t networkItem) { - return CLwipIf::getInstance().getChannel(networkItem); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -const char* CWifi::SSID() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getSSID(); - } - return ""; -} - -/* -------------------------------------------------------------------------- */ -uint8_t* CWifi::BSSID(uint8_t* bssid) { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getBSSID(bssid); - } - return nullptr; -} - -/* -------------------------------------------------------------------------- */ -int32_t CWifi::RSSI() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getRSSI(); - } - return 0; -} - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::encryptionType() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getEncryptionType(); - } - return 0; -} - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::status() { -/* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getWifiStatus(); -} - -/* -------------------------------------------------------------------------- */ -int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { -/* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getHostByName(aHostname,aResult); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::lowPowerMode() { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().setLowPowerMode(); -} - -/* -------------------------------------------------------------------------- */ -void CWifi::noLowPowerMode() { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().resetLowPowerMode(); -} - -uint8_t CWifi::reasonCode() { - return 0; -} - -unsigned long CWifi::getTime() { - return 0; -} - - - -void CWifi::setTimeout(unsigned long timeout) { - (void)(timeout); -} - - -CWifi WiFi; +// /* -------------------------------------------------------------------------- */ +// IPAddress CWifi::localIP() { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return IPAddress(ni->getIpAdd()); +// } +// return IPAddress((uint32_t)0); +// } + +// /* -------------------------------------------------------------------------- */ +// IPAddress CWifi::subnetMask() { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return IPAddress(ni->getNmAdd()); +// } +// return IPAddress((uint32_t)0); +// } + +// /* -------------------------------------------------------------------------- */ +// IPAddress CWifi::gatewayIP() { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return IPAddress(ni->getGwAdd()); +// } +// return IPAddress((uint32_t)0); +// } + +// /* -------------------------------------------------------------------------- */ +// IPAddress CWifi::dnsIP(int n) { +// return CLwipIf::getInstance().getDns(n); +// } + +// /* -------------------------------------------------------------------------- */ +// const char* CWifi::SSID(uint8_t networkItem) { +// return CLwipIf::getInstance().getSSID(networkItem); +// } +// /* -------------------------------------------------------------------------- */ + +// /* -------------------------------------------------------------------------- */ +// int32_t CWifi::RSSI(uint8_t networkItem) { +// return CLwipIf::getInstance().getRSSI(networkItem); +// } +// /* -------------------------------------------------------------------------- */ + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::encryptionType(uint8_t networkItem) { +// return CLwipIf::getInstance().getEncrType(networkItem); +// } +// /* -------------------------------------------------------------------------- */ + +// /* -------------------------------------------------------------------------- */ +// uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { +// return CLwipIf::getInstance().getBSSID(networkItem,bssid); +// } +// /* -------------------------------------------------------------------------- */ + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::channel(uint8_t networkItem) { +// return CLwipIf::getInstance().getChannel(networkItem); +// } +// /* -------------------------------------------------------------------------- */ + +// /* -------------------------------------------------------------------------- */ +// const char* CWifi::SSID() { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return ni->getSSID(); +// } +// return ""; +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t* CWifi::BSSID(uint8_t* bssid) { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return ni->getBSSID(bssid); +// } +// return nullptr; +// } + +// /* -------------------------------------------------------------------------- */ +// int32_t CWifi::RSSI() { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return ni->getRSSI(); +// } +// return 0; +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::encryptionType() { +// /* -------------------------------------------------------------------------- */ +// if(ni != nullptr) { +// return ni->getEncryptionType(); +// } +// return 0; +// } + +// /* -------------------------------------------------------------------------- */ +// uint8_t CWifi::status() { +// /* -------------------------------------------------------------------------- */ +// return CLwipIf::getInstance().getWifiStatus(); +// } + +// /* -------------------------------------------------------------------------- */ +// int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { +// /* -------------------------------------------------------------------------- */ +// return CLwipIf::getInstance().getHostByName(aHostname,aResult); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::lowPowerMode() { +// /* -------------------------------------------------------------------------- */ +// CLwipIf::getInstance().setLowPowerMode(); +// } + +// /* -------------------------------------------------------------------------- */ +// void CWifi::noLowPowerMode() { +// /* -------------------------------------------------------------------------- */ +// CLwipIf::getInstance().resetLowPowerMode(); +// } + +// uint8_t CWifi::reasonCode() { +// return 0; +// } + +// unsigned long CWifi::getTime() { +// return 0; +// } + + + +// void CWifi::setTimeout(unsigned long timeout) { +// (void)(timeout); +// } + + +// CWifi WiFi; diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index ffe55cbf..3abde923 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -8,7 +8,11 @@ #define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" +#ifdef ARDUINO_PORTENTA_C33 // TODO Instantiate the drivers for wifi with default configuration parameters +// ESPHostFGDriver WifiDriver; // Instantiate a global variable from CWifiStation calling it WiFi +inline CWifiStation WiFi; +#endif // ARDUINO_PORTENTA_C33 From 4c86ebf70b3988176c4285ac7d107f9535d0ab65 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 2 Jan 2024 16:09:22 +0100 Subject: [PATCH 24/79] added scanforap method --- libraries/lwIpWrapper/src/CNetIf.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index e14ab239..d944e4a3 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -292,6 +292,7 @@ CNetIf::CNetIf(NetworkDriver *driver) } int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { + CLwipIf::getInstance(); // This call is required in order to setup the network stack driver->begin(); ip_addr_t _ip = fromArduinoIP(ip); @@ -631,6 +632,23 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { return rv; } +int CWifiStation::scanForAp() { + // arduino::lock(); + access_points.clear(); // FIXME create access_points vector + + int res = CEspControl::getInstance().getAccessPointScanList(access_points); + if (res == ESP_CONTROL_OK) { + res = WL_SCAN_COMPLETED; + } + // else { + // res = WL_NO_SSID_AVAIL; // TODO + // } + + // arduino::unlock(); + + return res; +} + // disconnect int CWifiStation::disconnectFromAp() { return CEspControl::getInstance().disconnectAccessPoint(); @@ -880,10 +898,6 @@ int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t c return rv; } -int CWifiSoftAp::stopSoftAp() { - -} - err_t CWifiSoftAp::init(struct netif* ni) { // Setting up netif #if LWIP_NETIF_HOSTNAME @@ -922,7 +936,7 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { // p may be a chain of pbufs if(p->next != nullptr) { buf = (uint8_t*) malloc(size*sizeof(uint8_t)); - if(buf == nullptr) {\ + if(buf == nullptr) { // NETIF_STATS_INCREMENT_ERROR(this->stats, ERR_MEM); // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); errval = ERR_MEM; From b3713312b24c0b32cdefcec762e3bb14d7e9d786 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 4 Jan 2024 15:10:01 +0100 Subject: [PATCH 25/79] added comment --- libraries/Ethernet/src/EthernetC33.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/EthernetC33.h b/libraries/Ethernet/src/EthernetC33.h index 4ff7daf0..41288040 100644 --- a/libraries/Ethernet/src/EthernetC33.h +++ b/libraries/Ethernet/src/EthernetC33.h @@ -24,4 +24,4 @@ inline EthernetC33Driver EthernetDriver(2, 2, mem_malloc, 1536); // FIXME Instantiate a global variable from CEth, calling it Ethernet inline CEth Ethernet(&EthernetDriver); -#endif +#endif // ARDUINO_PORTENTA_C33 From 1c588992e1e50e8d4427c1d8ac7a6ae017b7615f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 4 Jan 2024 15:11:00 +0100 Subject: [PATCH 26/79] reimplementing Server class with ethernet and wifi subclasses --- libraries/Ethernet/src/EthernetClient.h | 28 +++-- libraries/Ethernet/src/EthernetServer.h | 40 ++---- libraries/WiFi/src/WiFiClient.h | 31 +++-- libraries/WiFi/src/WiFiServer.h | 41 ++---- libraries/lwIpWrapper/src/lwipClient.cpp | 154 +++++++++++++++-------- libraries/lwIpWrapper/src/lwipClient.h | 50 +++++--- libraries/lwIpWrapper/src/lwipServer.cpp | 151 +++++++++++++--------- libraries/lwIpWrapper/src/lwipServer.h | 53 +++++--- 8 files changed, 316 insertions(+), 232 deletions(-) diff --git a/libraries/Ethernet/src/EthernetClient.h b/libraries/Ethernet/src/EthernetClient.h index 7bb5cca2..7e201c76 100644 --- a/libraries/Ethernet/src/EthernetClient.h +++ b/libraries/Ethernet/src/EthernetClient.h @@ -1,17 +1,23 @@ -#ifndef ARDUINO_LWIP_ETHERNET_CLIENT_H -#define ARDUINO_LWIP_ETHERNET_CLIENT_H - +#pragma once #include "lwipClient.h" class EthernetClient : public lwipClient { public: - EthernetClient() { - this->bindCNetIf(Ethernet); - } - EthernetClient(struct tcp_pcb *pcb) : lwipClient(pcb) { - this->bindCNetIf(Ethernet); - } -}; + EthernetClient() { + } + EthernetClient(struct tcp_pcb *pcb, lwipServer *server) + : lwipClient(pcb, server) { + } + EthernetClient(lwipClient c) + : lwipClient(c) { + } + + int connect(IPAddress ip, uint16_t port) { + auto res = lwipClient::connect(ip, port); -#endif \ No newline at end of file + this->bindCNetIf(Ethernet); + + return res; + } +}; diff --git a/libraries/Ethernet/src/EthernetServer.h b/libraries/Ethernet/src/EthernetServer.h index 2afb5060..302af571 100644 --- a/libraries/Ethernet/src/EthernetServer.h +++ b/libraries/Ethernet/src/EthernetServer.h @@ -1,36 +1,16 @@ -#ifndef ARDUINO_LWIP_ETHERNET_SERVER_H -#define ARDUINO_LWIP_ETHERNET_SERVER_H - - +#pragma once #include "lwipServer.h" #include "EthernetClient.h" -class EthernetServer : public lwipServer { - public: - EthernetServer() {} - EthernetServer(uint16_t port) : lwipServer(port) {} - - EthernetClient available() { - accept(); +class EthernetServer: public lwipServer { +public: + void begin() { + lwipServer::begin(); + this->bindCNetIf(WiFi); + } - for (int n = 0; n < MAX_CLIENT; n++) { - if (_tcp_client[n] != NULL) { - if (_tcp_client[n]->pcb != NULL) { - EthernetClient client(_tcp_client[n]); - uint8_t s = client.status(); - if (s == TCP_ACCEPTED) { - if (client.available()) { - return client; - } - } - } - } - } - - struct tcp_struct *default_client = NULL; - return EthernetClient(default_client); - } + EthernetClient available() { + return EthernetClient(lwipServer::available()); + } }; - -#endif \ No newline at end of file diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index e6f26fd6..98761c51 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -1,18 +1,23 @@ -#ifndef ARDUINO_LWIP_WIFI_CLIENT_H -#define ARDUINO_LWIP_WIFI_CLIENT_H - +#pragma once #include "lwipClient.h" -class WiFiClient : public lwipClient { - public: - WiFiClient() { - this->bindCNetIf(WiFi); - } - WiFiClient(struct tcp_pcb *pcb) : lwipClient(pcb) { - this->bindCNetIf(WiFi); - } -}; +class WiFiClient: public lwipClient { +public: + WiFiClient() { + } + WiFiClient(struct tcp_pcb *pcb, lwipServer *server) + : lwipClient(pcb, server) { + } + WiFiClient(lwipClient c) + : lwipClient(c) { + } -#endif + int connect(IPAddress ip, uint16_t port) { + auto res = lwipClient::connect(ip, port); + this->bindCNetIf(WiFi); + + return res; + } +}; diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index 1199814f..c72c8659 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -1,35 +1,16 @@ -#ifndef ARDUINO_LWIP_WIFI_SERVER_H -#define ARDUINO_LWIP_WIFI_SERVER_H - +#pragma once #include "lwipServer.h" -#include "WiFiClient.h" - -class WiFiServer : public lwipServer { - public: - WiFiServer() {} - WiFiServer(uint16_t port) : lwipServer(port) {} +#include "lwipClient.h" - WiFiClient available() { - accept(); +class WiFiServer: public lwipServer { +public: + void begin() { + lwipServer::begin(); + this->bindCNetIf(WiFi); + } - for (int n = 0; n < MAX_CLIENT; n++) { - if (_tcp_client[n] != NULL) { - if (_tcp_client[n]->pcb != NULL) { - WiFiClient client(_tcp_client[n]); - uint8_t s = client.status(); - if (s == TCP_ACCEPTED) { - if (client.available()) { - return client; - } - } - } - } - } - - struct tcp_struct *default_client = NULL; - return WiFiClient(default_client); - } + WiFiClient available() { + return WiFiClient(lwipServer::available()); + } }; - -#endif \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 91919e99..99821430 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -21,17 +21,61 @@ static err_t _lwip_tcp_sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len) void _lwip_tcp_err_callback(void *arg, err_t err); lwipClient::lwipClient() - : pcb(NULL) { +: tcp_info(new tcp_info_t) +{ + // tcp_info = std::shared_ptr(new tcp_info_t); + this->tcp_info->state = TCP_NONE; + this->tcp_info->pcb = nullptr; + this->tcp_info->server = nullptr; + this->tcp_info->pbuf_offset = 0; + this->tcp_info->pbuf_head = nullptr; } /* Deprecated constructor. Keeps compatibility with W5100 architecture sketches but sock is ignored. */ -lwipClient::lwipClient(uint8_t sock) - : pcb(NULL) { +lwipClient::lwipClient(uint8_t sock) {} + +lwipClient::lwipClient(struct tcp_pcb* pcb, lwipServer *server) +: tcp_info(new tcp_info_t) +{ + // tcp_info = std::shared_ptr(new tcp_info_t); + this->tcp_info->state = TCP_ACCEPTED; + this->tcp_info->pcb = pcb; + this->tcp_info->server = server; + this->tcp_info->pbuf_offset = 0; + this->tcp_info->pbuf_head = nullptr; + + tcp_arg(this->tcp_info->pcb, this); + + tcp_err(this->tcp_info->pcb, _lwip_tcp_err_callback); // FIXME make this a user callback? + + /* initialize LwIP tcp_recv callback function */ + tcp_recv(this->tcp_info->pcb, _lwip_tcp_recv_callback); + + /* initialize LwIP tcp_sent callback function */ + tcp_sent(this->tcp_info->pcb, _lwip_tcp_sent_callback); // FIXME do we actually need it? } -lwipClient::lwipClient(struct tcp_pcb* pcb) -: pcb(pcb) { +lwipClient::lwipClient(const lwipClient& c) +: tcp_info(c.tcp_info), _timeout(c._timeout), _ip(c._ip) { +} + +lwipClient& lwipClient::operator=(const lwipClient& rhs) { + this->tcp_info = rhs.tcp_info; + this->_timeout = rhs._timeout; + this->_ip = rhs._ip; + return *this; +} + +lwipClient::lwipClient(lwipClient&& c) +: tcp_info(std::move(c.tcp_info)), _timeout(std::move(c._timeout)), _ip(std::move(c._ip)) { +} + +lwipClient& lwipClient::operator=(lwipClient&& rhs) { + this->tcp_info = std::move(rhs.tcp_info); + this->_timeout = std::move(rhs._timeout); + this->_ip = std::move(rhs._ip); + return *this; } lwipClient::~lwipClient() { @@ -51,27 +95,30 @@ int lwipClient::connect(const char* host, uint16_t port) { int lwipClient::connect(IPAddress ip, uint16_t port) { err_t err = ERR_OK; - this->pcb = tcp_new(); - if(this->pcb == nullptr) { + // the connect method is only connected when trying to connect a client to a server + // and not when a client is created out of a listening socket + this->tcp_info->pcb = tcp_new(); + + if(this->tcp_info->pcb == nullptr) { // return ; // TODO find the proper error code return err; } - tcp_err(this->pcb, _lwip_tcp_err_callback); // FIXME make this a user callback? + tcp_err(this->tcp_info->pcb, _lwip_tcp_err_callback); // FIXME make this a user callback? if(err != ERR_OK) { return err; } - this->state = TCP_NONE; + this->tcp_info->state = TCP_NONE; - tcp_arg(this->pcb, this); + tcp_arg(this->tcp_info->pcb, this); this->_ip = fromArduinoIP(ip); // FIXME this doesn't include timeout of connection, does lwip have it by default? err = tcp_connect( - this->pcb, &this->_ip, port, // FIXME check if _ip gets copied + this->tcp_info->pcb, &this->_ip, port, // FIXME check if _ip gets copied _lwip_tcp_connected_callback // FIXME we need to define a static private function ); return err; @@ -107,7 +154,7 @@ err_t lwipClient::connected_callback(struct tcp_pcb* tpcb, err_t err) { return ERR_ARG; } - this->state = TCP_CONNECTED; + this->tcp_info->state = TCP_CONNECTED; /* initialize LwIP tcp_recv callback function */ tcp_recv(tpcb, _lwip_tcp_recv_callback); @@ -183,14 +230,14 @@ err_t lwipClient::recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err) return ERR_OK; } arduino::lock(); - if(this->state == TCP_CONNECTED) { - if (this->pbuf_head == nullptr) { + if(this->tcp_info->state == TCP_CONNECTED) { + if (this->tcp_info->pbuf_head == nullptr) { // no need to increment the references of the pbuf, // since it is already 1 and lwip shifts the control to this code - this->pbuf_head = p; + this->tcp_info->pbuf_head = p; } else { - // no need to increment the references of p, since it is already 1 and the only reference is this->pbuf_head->next - pbuf_cat(this->pbuf_head, p); + // no need to increment the references of p, since it is already 1 and the only reference is this->tcp_info->pbuf_head->next + pbuf_cat(this->tcp_info->pbuf_head, p); } ret_err = ERR_OK; @@ -211,14 +258,14 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { uint8_t bytes_to_send = 0; do { - bytes_to_send = min(size - (buffer - buffer_cursor), tcp_sndbuf(this->pcb)); + bytes_to_send = min(size - (buffer - buffer_cursor), tcp_sndbuf(this->tcp_info->pcb)); /* * TODO: Look into the following flags, especially for write of 1 byte * TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack * TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent */ - err_t res = tcp_write(this->pcb, buffer_cursor, bytes_to_send, TCP_WRITE_FLAG_COPY); + err_t res = tcp_write(this->tcp_info->pcb, buffer_cursor, bytes_to_send, TCP_WRITE_FLAG_COPY); if(res == ERR_OK) { buffer_cursor += bytes_to_send; @@ -228,7 +275,7 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { // TODO understand if the tcp_write will send data if the buffer is not full // force send only if we filled the send buffer - // if (ERR_OK != tcp_output(this->pcb)) { + // if (ERR_OK != tcp_output(this->tcp_info->pcb)) { // // return 0; // break; // } @@ -246,11 +293,11 @@ int lwipClient::read() { } int lwipClient::read(uint8_t* buffer, size_t size) { - if(size==0 || buffer==nullptr || this->pbuf_head==nullptr) { + if(size==0 || buffer==nullptr || this->tcp_info->pbuf_head==nullptr) { return 0; // TODO extend checks } // copy data from the lwip buffer to the app provided buffer - // TODO look into pbuf_get_contiguous(this->pbuf_head, buffer_cursor, len); + // TODO look into pbuf_get_contiguous(this->tcp_info->pbuf_head, buffer_cursor, len); // pbuf_get_contiguous: returns the pointer to the payload if size <= pbuf.len // otherwise copies data in the user provided buffer. This can be used in a callback paradigm, // in order to avoid memcpy data @@ -261,7 +308,7 @@ int lwipClient::read(uint8_t* buffer, size_t size) { * we need to account that */ arduino::lock(); - uint16_t copied = pbuf_copy_partial(this->pbuf_head, buffer, size, this->pbuf_offset); + uint16_t copied = pbuf_copy_partial(this->tcp_info->pbuf_head, buffer, size, this->tcp_info->pbuf_offset); this->free_pbuf_chain(copied); // __enable_irq(); @@ -278,31 +325,31 @@ int lwipClient::peek() { } arduino::lock(); - b = pbuf_get_at(this->pbuf_head, 0); // TODO test this + b = pbuf_get_at(this->tcp_info->pbuf_head, 0); // TODO test this arduino::unlock(); return b; } void lwipClient::flush() { - if ((this->pcb == NULL)) { + if ((this->tcp_info->pcb == NULL)) { return; } - tcp_output(this->pcb); + tcp_output(this->tcp_info->pcb); } void lwipClient::stop() { - tcp_recv(this->pcb, nullptr); - tcp_sent(this->pcb, nullptr); - tcp_poll(this->pcb, nullptr, 0); - tcp_err(this->pcb, nullptr); - tcp_accept(this->pcb, nullptr); + tcp_recv(this->tcp_info->pcb, nullptr); + tcp_sent(this->tcp_info->pcb, nullptr); + tcp_poll(this->tcp_info->pcb, nullptr, 0); + tcp_err(this->tcp_info->pcb, nullptr); + tcp_accept(this->tcp_info->pcb, nullptr); - if(this->pcb != nullptr) { - err_t err = tcp_close(this->pcb); - this->state = TCP_CLOSING; + if(this->tcp_info->pcb != nullptr) { + err_t err = tcp_close(this->tcp_info->pcb); + this->tcp_info->state = TCP_CLOSING; - this->pcb = nullptr; + this->tcp_info->pcb = nullptr; // FIXME if err != ERR_OK retry, there may be memory issues, retry? } @@ -315,25 +362,26 @@ void lwipClient::stop() { } uint8_t lwipClient::connected() { - return this->state != TCP_NONE; //TODO + return this->tcp_info->state == TCP_CONNECTED || this->tcp_info->state == TCP_ACCEPTED; } uint8_t lwipClient::status() { - if (this == NULL) { + if (this == nullptr) { return TCP_NONE; } - return this->state; + return this->tcp_info->state; } // the next function allows us to use the client returned by // EthernetServer::available() as the condition in an if-statement. lwipClient::operator bool() { - return (this->pcb != nullptr); + return (this->tcp_info->pcb != nullptr); } bool lwipClient::operator==(const lwipClient& rhs) { - // return pcb == rhs.this && this->pcb == rhs.this->pcb; + // return pcb == rhs.this && this->tcp_info->pcb == rhs.this->tcp_info->pcb; + return this->tcp_info == rhs.tcp_info; } /* This function is not a function defined by Arduino. This is a function @@ -347,13 +395,13 @@ uint8_t lwipClient::getSocketNumber() { // this allows the user to avoid using temporary buffers size_t lwipClient::read_until_token( const uint8_t* buffer, uint16_t buffer_size, char* token, bool &found) { - if(buffer_size==0 || buffer==nullptr || this->pbuf_head==nullptr) { + if(buffer_size==0 || buffer==nullptr || this->tcp_info->pbuf_head==nullptr) { return 0; // TODO extend checks } arduino::lock(); // TODO check that the buffer size is less than the token len - uint16_t offset=this->pbuf_offset; + uint16_t offset=this->tcp_info->pbuf_offset; /* iterate over pbufs until: * - the first occurrence of token * - the provided buffer is full @@ -362,7 +410,7 @@ size_t lwipClient::read_until_token( size_t tkn_len = strlen(token); // FIXME if we have already found the token we hare wasting time to check the entire buffer again - uint16_t position = pbuf_memfind(this->pbuf_head, token, tkn_len, this->pbuf_offset); // TODO check efficiency of this function + uint16_t position = pbuf_memfind(this->tcp_info->pbuf_head, token, tkn_len, this->tcp_info->pbuf_offset); // TODO check efficiency of this function uint16_t buf_copy_len = buffer_size; // TODO triple check the indices of these conditions @@ -383,7 +431,7 @@ size_t lwipClient::read_until_token( found = false; } - uint16_t copied = pbuf_copy_partial(this->pbuf_head, (uint8_t*)buffer, buf_copy_len, this->pbuf_offset); + uint16_t copied = pbuf_copy_partial(this->tcp_info->pbuf_head, (uint8_t*)buffer, buf_copy_len, this->tcp_info->pbuf_offset); this->free_pbuf_chain(copied); arduino::unlock(); @@ -399,12 +447,12 @@ void lwipClient::free_pbuf_chain(uint16_t copied) { * taking into account the previously not entirely consumed pbuf */ uint32_t tobefreed = 0; - copied += this->pbuf_offset; + copied += this->tcp_info->pbuf_offset; // in order to clean up the chain we need to find the pbuf in the last pbuf in the chain // that got completely consumed by the application, dechain it from it successor and delete the chain before it - struct pbuf *head = this->pbuf_head, *last=head, *prev=nullptr; // FIXME little optimization prev can be substituted by last->next + struct pbuf *head = this->tcp_info->pbuf_head, *last=head, *prev=nullptr; // FIXME little optimization prev can be substituted by last->next while(last!=nullptr && last->len + tobefreed <= copied) { tobefreed += last->len; @@ -415,22 +463,20 @@ void lwipClient::free_pbuf_chain(uint16_t copied) { // dechain if we are not at the end of the chain (last == nullptr) // and if we haven't copied entirely the first pbuf (prev == nullptr) (head == last) // if we reached the end of the chain set the this pbuf pointer to nullptr - if(prev != nullptr && last != nullptr) { + if(prev != nullptr) { prev->next = nullptr; - this->pbuf_head = last; - } if(last == nullptr) { - this->pbuf_head = nullptr; + this->tcp_info->pbuf_head = last; } - // the chain that is referenced by head is detached by the one referenced by this->pbuf_head + // the chain that is referenced by head is detached by the one referenced by this->tcp_info->pbuf_head // free the chain if we haven't copied entirely the first pbuf (prev == nullptr) - if(this->pbuf_head != head) { + if(this->tcp_info->pbuf_head != head) { uint8_t refs = pbuf_free(head); } - this->pbuf_offset = copied - tobefreed; // This offset should be referenced to the first pbuf in queue + this->tcp_info->pbuf_offset = copied - tobefreed; // This offset should be referenced to the first pbuf in queue // acknowledge the received data - tcp_recved(this->pcb, copied); + tcp_recved(this->tcp_info->pcb, copied); arduino::unlock(); } diff --git a/libraries/lwIpWrapper/src/lwipClient.h b/libraries/lwIpWrapper/src/lwipClient.h index 5188f42e..17e9985d 100644 --- a/libraries/lwIpWrapper/src/lwipClient.h +++ b/libraries/lwIpWrapper/src/lwipClient.h @@ -4,22 +4,31 @@ #include #include #include "CNetIf.h" +#include "lwipServer.h" +#include // TODO improve documentation +enum _tcp_state_t: uint8_t { + TCP_NONE = 0, + TCP_ACCEPTED, + TCP_CONNECTED, + TCP_CLOSING +}; + class lwipClient : public arduino::Client { public: lwipClient(); lwipClient(uint8_t sock); - lwipClient(struct tcp_pcb* tcpClient); // FIXME this should be a private constructor, friend of Server + lwipClient(struct tcp_pcb* tcpClient, lwipServer *server); // FIXME this should be a private constructor, friend of Server // disable copy constructor - lwipClient(const lwipClient&) = delete; - void operator=(const lwipClient&) = delete; + lwipClient(const lwipClient&); + lwipClient& operator=(const lwipClient&); // keep move constructor lwipClient(lwipClient&&); - void operator=(lwipClient&&); + lwipClient& operator=(lwipClient&&); virtual ~lwipClient(); @@ -30,7 +39,9 @@ class lwipClient : public arduino::Client { virtual size_t write(uint8_t); virtual size_t write(const uint8_t* buf, size_t size); - inline virtual int available() { return this->pbuf_head == nullptr ? 0 : this->pbuf_head->tot_len; } + inline virtual int available() { + return this->tcp_info->pbuf_head == nullptr ? 0 : this->tcp_info->pbuf_head->tot_len - this->tcp_info->pbuf_offset; + } virtual int read(); virtual int read(uint8_t* buf, size_t size); @@ -56,20 +67,20 @@ class lwipClient : public arduino::Client { uint8_t getSocketNumber(); virtual uint16_t localPort() { - return (this->pcb->local_port); + return (this->tcp_info->pcb->local_port); }; virtual IPAddress remoteIP() { - return (IPAddress(this->pcb->remote_ip.addr)); + return (IPAddress(this->tcp_info->pcb->remote_ip.addr)); }; virtual uint16_t remotePort() { - return (this->pcb->remote_port); + return (this->tcp_info->pcb->remote_port); }; void setConnectionTimeout(uint16_t timeout) { _timeout = timeout; } void bindCNetIf(CNetIf &n) { - tcp_bind_netif(this->pcb, n.getNi()); + tcp_bind_netif(this->tcp_info->pcb, n.getNi()); } friend class lwipServer; @@ -77,18 +88,17 @@ class lwipClient : public arduino::Client { using Print::write; private: - enum _tcp_state_t: uint8_t { - TCP_NONE = 0, - // TCP_ACCEPTED, - TCP_CONNECTED, - TCP_CLOSING + // TCP related info of the socket + struct tcp_info_t { + _tcp_state_t state; + struct pbuf* pbuf_head; + struct tcp_pcb* pcb; + uint16_t pbuf_offset; + // this pointer is used to correctly clean the lwipClient when created from a server class + lwipServer* server; }; - // TCP related info of the socket - _tcp_state_t state = TCP_NONE; - struct pbuf* pbuf_head = nullptr; - struct tcp_pcb* pcb = nullptr; - uint16_t pbuf_offset = 0; + std::shared_ptr tcp_info; uint16_t _timeout = 10000; ip_addr_t _ip; @@ -100,3 +110,5 @@ class lwipClient : public arduino::Client { friend err_t _lwip_tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err); friend err_t _lwip_tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err); }; + +inline const lwipClient CLIENT_NONE(nullptr, nullptr); \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipServer.cpp b/libraries/lwIpWrapper/src/lwipServer.cpp index 768b5887..151b1f9d 100644 --- a/libraries/lwIpWrapper/src/lwipServer.cpp +++ b/libraries/lwIpWrapper/src/lwipServer.cpp @@ -6,38 +6,38 @@ extern "C" { #include "lwipClient.h" #include "lwipServer.h" +err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err); + +lwipServer::lwipServer(const IPAddress &listen_ip, uint16_t port) +: _port(port), listen_address(listen_ip), server_pcb(nullptr) { +} + lwipServer::lwipServer(uint16_t port) -{ - _port = port; - for (int i = 0; i < MAX_CLIENT; i++) { - _tcp_client[i] = {}; - } - _tcp_server = {}; +: _port(port), listen_address(INADDR_NONE), server_pcb(nullptr) { } void lwipServer::begin() { - if (_tcp_server.pcb != NULL) { + if (server_pcb != NULL) { return; } - _tcp_server.pcb = tcp_new(); + server_pcb = tcp_new(); - if (_tcp_server.pcb == NULL) { + if (server_pcb == NULL) { return; } - tcp_arg(_tcp_server.pcb, &_tcp_client); - _tcp_server.state = TCP_NONE; + tcp_arg(server_pcb, this); - if (ERR_OK != tcp_bind(_tcp_server.pcb, IP_ADDR_ANY, _port)) { - memp_free(MEMP_TCP_PCB, _tcp_server.pcb); - _tcp_server.pcb = NULL; + if (ERR_OK != tcp_bind(server_pcb, IP_ADDR_ANY, _port)) { // TODO Put the listen address here + memp_free(MEMP_TCP_PCB, server_pcb); + server_pcb = NULL; return; } - _tcp_server.pcb = tcp_listen(_tcp_server.pcb); - tcp_accept(_tcp_server.pcb, tcp_accept_callback); + server_pcb = tcp_listen(server_pcb); + tcp_accept(server_pcb, tcp_accept_callback); } void lwipServer::begin(uint16_t port) @@ -46,41 +46,64 @@ void lwipServer::begin(uint16_t port) begin(); } -void lwipServer::accept() -{ - /* Free client if disconnected */ - for (int n = 0; n < MAX_CLIENT; n++) { - if (_tcp_client[n] != NULL) { - // lwipClient client(_tcp_client[n]); // FIXME - // if (client.status() == TCP_CLOSING) { - // mem_free(_tcp_client[n]); - // _tcp_client[n] = NULL; - // } +// void lwipServer::clean() { +// // this index is a placeholder to the first empty position that needs to be filled +// int8_t moveto = -1; + +// new_size = size; +// // remove all the closed clients +// for (int i=0; i < size; i++) { +// if (client.status() == TCP_CLOSING) { +// delete clients[n]; +// clients[n] = nullptr; +// new_size--; + +// if(moveto == -1) { +// moveto = n; +// } +// } + +// if(moveto >= 0 && clients[n] != nullptr) { +// clients[moveto] = clients[n]; +// clients[n] = nullptr; +// moveto++; +// } +// } + +// size = new_size +// } + +void lwipServer::remove(lwipClient* client) { + bool found = false; + for (int i=0; i < size; i++) { + if(found) { + clients[i-1] = clients[i]; + } else if(*client == *clients[i]) { + found = true; } } + + delete clients[--size]; + clients[size] = nullptr; +} + +void lwipServer::accept(struct tcp_pcb* new_client) { + // this->clean(); + + if(size < MAX_CLIENT-1) { + clients[size] = new lwipClient(new_client, this); + size++; + clients_available++; + } } lwipClient lwipServer::available() { - accept(); - - for (int n = 0; n < MAX_CLIENT; n++) { - if (_tcp_client[n] != NULL) { - if (_tcp_client[n]->pcb != NULL) { - // lwipClient client(_tcp_client[n]); // FIXME - // uint8_t s = client.status(); - // if (s == TCP_ACCEPTED) { - // if (client.available()) { - // return client; - // } - // } - } - } + if(size > 0 && clients_available>0) { + return *clients[size-clients_available--]; // TODO verify index + } else { + return CLIENT_NONE; } - - struct tcp_struct* default_client = NULL; - return lwipClient(); // FIXME - // return lwipClient(default_client); } size_t lwipServer::write(uint8_t b) @@ -88,23 +111,29 @@ size_t lwipServer::write(uint8_t b) return write(&b, 1); } -size_t lwipServer::write(const uint8_t* buffer, size_t size) -{ - size_t n = 0; - - accept(); - - for (int n = 0; n < MAX_CLIENT; n++) { - if (_tcp_client[n] != NULL) { - if (_tcp_client[n]->pcb != NULL) { - // lwipClient client(_tcp_client[n]); - // uint8_t s = client.status(); - // if (s == TCP_ACCEPTED) { - // n += client.write(buffer, size); - // } - } - } +size_t lwipServer::write(const uint8_t* buffer, size_t size) { + size_t written=0; + // this->clean(); + + for (int i = 0; i < MAX_CLIENT; i++) { + written += clients[i]->write(buffer, size); } - return n; + return written; } + +err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err) { + lwipServer* server = (lwipServer*) arg; + err_t ret_err; + + /* set priority for the newly accepted tcp connection newpcb */ + tcp_setprio(newpcb, TCP_PRIO_MIN); + + if ((arg != NULL) && (ERR_OK == err)) { + server->accept(newpcb); + } else { + tcp_close(newpcb); + ret_err = ERR_ARG; + } + return ret_err; +} \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipServer.h b/libraries/lwIpWrapper/src/lwipServer.h index e7d4456b..c08514ad 100644 --- a/libraries/lwIpWrapper/src/lwipServer.h +++ b/libraries/lwIpWrapper/src/lwipServer.h @@ -1,27 +1,52 @@ -#ifndef _ARDUINO_LWIP_SERVER_H -#define _ARDUINO_LWIP_SERVER_H +#pragma once -#include "Server.h" -#include "lwipTcp.h" +#include +#include +#include +// #include "lwipClient.h" class lwipClient; -class lwipServer : public Server { -protected: - uint16_t _port; - struct tcp_struct _tcp_server; - struct tcp_struct* _tcp_client[MAX_CLIENT]; - - void accept(void); - +class lwipServer: public Server { public: + lwipServer(const IPAddress &listen_ip = INADDR_NONE, uint16_t port = 80); lwipServer(uint16_t port = 80); lwipClient available(); + virtual void begin(); virtual void begin(uint16_t port); virtual size_t write(uint8_t); virtual size_t write(const uint8_t* buf, size_t size); using Print::write; -}; -#endif \ No newline at end of file + void bindCNetIf(CNetIf &n) { + tcp_bind_netif(this->server_pcb, n.getNi()); + } +protected: + /* + * these methods are used to insert and remove lwipClients in lwipServer class + * the idea is the following: + * - a client is created by lwip, we wrap it around a lwipClient class and and returned by available() call + * - the client is inserted in the last empty position of the clients array + * - when a client connection is closed (by calling stop on it or delete on the client) + * the server is notified and the remove() method is called thus the client is removed from the server list. + */ + void accept(struct tcp_pcb* new_client); + // void clean(); + void remove(lwipClient* client); + + uint16_t _port; + const IPAddress &listen_address; + tcp_pcb* server_pcb; + uint16_t port; + + // this array in managed as a fixed size list with all the null values in the back. + // size var indicates how full is the array + // the total number of pcb should be MEMP_NUM_TCP_PCB, -1 that is the server PCB +private: + uint8_t size=0, clients_available=0; + lwipClient* clients[MAX_CLIENT-1]; + + friend err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err); + friend lwipClient; +}; From ed6886dc104b33eae51e6cc5b5e391fab56c552f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 4 Jan 2024 15:12:08 +0100 Subject: [PATCH 27/79] fixing bug of missing nullptr check --- libraries/lwIpWrapper/src/CNetIf.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index d944e4a3..c6668a63 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -293,7 +293,10 @@ CNetIf::CNetIf(NetworkDriver *driver) int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { CLwipIf::getInstance(); // This call is required in order to setup the network stack - driver->begin(); + + if(driver != nullptr) { + driver->begin(); + } ip_addr_t _ip = fromArduinoIP(ip); ip_addr_t _nm = fromArduinoIP(nm); From 10a05bd2e36c4585d2e68d3089b4d61249636422 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 4 Jan 2024 15:12:30 +0100 Subject: [PATCH 28/79] removed unused types --- libraries/lwIpWrapper/src/lwipTypes.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipTypes.h b/libraries/lwIpWrapper/src/lwipTypes.h index c108e15c..a0282de4 100644 --- a/libraries/lwIpWrapper/src/lwipTypes.h +++ b/libraries/lwIpWrapper/src/lwipTypes.h @@ -6,16 +6,6 @@ #include /* Exported types ------------------------------------------------------------*/ -/* TCP connection state */ -typedef enum { - TCP_NONE = 0, - TCP_CONNECTED, - TCP_RECEIVED, - TCP_SENT, - TCP_ACCEPTED, - TCP_CLOSING, -} tcp_client_states; - /* Struct to store received data */ struct pbuf_data { struct pbuf* p; // the packet buffer that was received @@ -31,11 +21,4 @@ struct udp_struct { std::function onDataArrival; }; -/* TCP structure */ -struct tcp_struct { - struct tcp_pcb* pcb; /* pointer on the current tcp_pcb */ - struct pbuf_data data; - tcp_client_states state; /* current connection state */ -}; - #endif From 42063d1c08108b28f1c04a0bb686f1461c79f426 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 4 Jan 2024 15:12:36 +0100 Subject: [PATCH 29/79] minor changes on file --- libraries/lwIpWrapper/src/CNetIf.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 8fd96445..8c96f1fe 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -1,6 +1,5 @@ #pragma once -// #define LWIP_USE_TIMER #define UNUSED(x) (void)(x) #define USE_LWIP_AS_LIBRARY @@ -80,7 +79,7 @@ typedef enum { NI_ETHERNET } NetIfType_t; -#define MAX_CLIENT 32 +#define MAX_CLIENT MEMP_NUM_TCP_PCB #define MAX_DHCP_TRIES 4 #define TIMEOUT_DNS_REQUEST 10000U @@ -97,7 +96,6 @@ typedef enum { #define INVALID_RESPONSE -4 class CLwipIf; -class lwipClient; /* Base class implements DHCP, derived class will switch it on or off */ class CNetIf: public NetworkInterface { @@ -331,7 +329,7 @@ class CLwipIf { // functions that handle DNS resolution // DNS servers are also set by dhcp #if LWIP_DNS - // add a dns server, priority set to 0 means it is the first being queryed, -1 means the last + // add a dns server, priority set to 0 means it is the first being queried, -1 means the last uint8_t addDnsServer(const IPAddress& aDNSServer, int8_t priority=-1); void clearDnsServers(); From e41294a2dcc515c026f57e26e6dab0a039787942 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 5 Jan 2024 10:47:01 +0100 Subject: [PATCH 30/79] Revert "defined Wifi global variable for network interface" This reverts commit c2db54f2cf7de3f985e7f70c84d49e0faf68567c. --- libraries/WiFi/src/WiFi.cpp | 620 ++++++++++++++++++------------------ libraries/WiFi/src/WiFiC3.h | 4 - 2 files changed, 310 insertions(+), 314 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index d91a212e..59e742a0 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -1,331 +1,331 @@ #include "WiFiC3.h" -// extern "C" void dhcps_start(struct netif *netif); +extern "C" void dhcps_start(struct netif *netif); -// /* -------------------------------------------------------------------------- */ -// CWifi::CWifi() : _timeout(50000), ni(nullptr) { -// } -// /* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +CWifi::CWifi() : _timeout(50000), ni(nullptr) { +} +/* -------------------------------------------------------------------------- */ -// /* -------------------------------------------------------------------------- */ -// const char* CWifi::firmwareVersion() { -// /* -------------------------------------------------------------------------- */ -// /* silly "dummy" implementation to keep compatibility, at the present -// the WiFi fw does not return any version number */ -// return WIFI_FIRMWARE_LATEST_VERSION; -// } +/* -------------------------------------------------------------------------- */ +const char* CWifi::firmwareVersion() { +/* -------------------------------------------------------------------------- */ + /* silly "dummy" implementation to keep compatibility, at the present + the WiFi fw does not return any version number */ + return WIFI_FIRMWARE_LATEST_VERSION; +} -// /* -------------------------------------------------------------------------- */ -// int CWifi::begin(const char* ssid) { -// /* -------------------------------------------------------------------------- */ -// ni = CLwipIf::getInstance().get(NI_WIFI_STATION); -// CLwipIf::getInstance().connectToAp(ssid, nullptr); -// if(ni != nullptr && !_useStaticIp) { -// ni->DhcpStart(); -// } +/* -------------------------------------------------------------------------- */ +int CWifi::begin(const char* ssid) { +/* -------------------------------------------------------------------------- */ + ni = CLwipIf::getInstance().get(NI_WIFI_STATION); + CLwipIf::getInstance().connectToAp(ssid, nullptr); + if(ni != nullptr && !_useStaticIp) { + ni->DhcpStart(); + } -// return CLwipIf::getInstance().getWifiStatus(); -// } + return CLwipIf::getInstance().getWifiStatus(); +} -// /* -------------------------------------------------------------------------- */ -// int CWifi::begin(const char* ssid, const char *passphrase) { -// /* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +int CWifi::begin(const char* ssid, const char *passphrase) { +/* -------------------------------------------------------------------------- */ -// ni = CLwipIf::getInstance().get(NI_WIFI_STATION); -// CLwipIf::getInstance().connectToAp(ssid, passphrase); -// if(ni != nullptr && !_useStaticIp) { -// ni->DhcpStart(); -// } + ni = CLwipIf::getInstance().get(NI_WIFI_STATION); + CLwipIf::getInstance().connectToAp(ssid, passphrase); + if(ni != nullptr && !_useStaticIp) { + ni->DhcpStart(); + } -// return CLwipIf::getInstance().getWifiStatus(); -// } - -// /* passphrase is needed so a default one will be set */ -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::beginAP(const char *ssid) { -// /* -------------------------------------------------------------------------- */ -// return beginAP(ssid,1); -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::beginAP(const char *ssid, uint8_t channel) { -// /* -------------------------------------------------------------------------- */ -// return beginAP(ssid,nullptr,channel); -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { -// /* -------------------------------------------------------------------------- */ -// return beginAP(ssid,passphrase,1); -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { -// /* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().getWifiStatus(); +} + +/* passphrase is needed so a default one will be set */ +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::beginAP(const char *ssid) { +/* -------------------------------------------------------------------------- */ + return beginAP(ssid,1); +} + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::beginAP(const char *ssid, uint8_t channel) { +/* -------------------------------------------------------------------------- */ + return beginAP(ssid,nullptr,channel); +} + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { +/* -------------------------------------------------------------------------- */ + return beginAP(ssid,passphrase,1); +} + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { +/* -------------------------------------------------------------------------- */ -// ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); -// CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); -// if(ni != nullptr) { + ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); + CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); + if(ni != nullptr) { -// dhcps_start(ni->getNi()); -// } + dhcps_start(ni->getNi()); + } -// return CLwipIf::getInstance().getWifiStatus(); -// } - - - -// /* -------------------------------------------------------------------------- */ -// void CWifi::config(IPAddress local_ip) { -// /* -------------------------------------------------------------------------- */ -// IPAddress _nm(255, 255, 255, 0); -// IPAddress _gw = local_ip; -// _gw[3] = 1; - -// _config(local_ip, _gw, _nm); -// } - -// extern uint8_t *IpAddress2uint8(IPAddress a); - -// /* -------------------------------------------------------------------------- */ -// void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { -// /* -------------------------------------------------------------------------- */ -// _useStaticIp = local_ip != INADDR_NONE; -// if(ni != nullptr) { -// ni->DhcpStop(); -// ni->DhcpNotUsed(); -// IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); -// IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); -// IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); -// } -// else { -// CNetIf::default_ip = local_ip; -// CNetIf::default_nm = subnet; -// CNetIf::default_gw = gateway; -// CNetIf::default_dhcp_server_ip = local_ip; -// } -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::config(IPAddress local_ip, IPAddress dns_server) { -// /* -------------------------------------------------------------------------- */ -// config(local_ip); -// CLwipIf::getInstance().addDns(dns_server); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { -// /* -------------------------------------------------------------------------- */ -// IPAddress _nm(255, 255, 255, 0); -// _config(local_ip, gateway, _nm); -// CLwipIf::getInstance().addDns(dns_server); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { -// /* -------------------------------------------------------------------------- */ -// _config(local_ip, gateway, subnet); -// CLwipIf::getInstance().addDns(dns_server); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::setDNS(IPAddress dns_server1) { -// /* -------------------------------------------------------------------------- */ -// CLwipIf::getInstance().addDns(dns_server1); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { -// /* -------------------------------------------------------------------------- */ -// CLwipIf::getInstance().addDns(dns_server1); -// CLwipIf::getInstance().addDns(dns_server2); + return CLwipIf::getInstance().getWifiStatus(); +} + + + +/* -------------------------------------------------------------------------- */ +void CWifi::config(IPAddress local_ip) { +/* -------------------------------------------------------------------------- */ + IPAddress _nm(255, 255, 255, 0); + IPAddress _gw = local_ip; + _gw[3] = 1; + + _config(local_ip, _gw, _nm); +} + +extern uint8_t *IpAddress2uint8(IPAddress a); + +/* -------------------------------------------------------------------------- */ +void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { +/* -------------------------------------------------------------------------- */ + _useStaticIp = local_ip != INADDR_NONE; + if(ni != nullptr) { + ni->DhcpStop(); + ni->DhcpNotUsed(); + IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); + IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); + IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); + } + else { + CNetIf::default_ip = local_ip; + CNetIf::default_nm = subnet; + CNetIf::default_gw = gateway; + CNetIf::default_dhcp_server_ip = local_ip; + } +} + +/* -------------------------------------------------------------------------- */ +void CWifi::config(IPAddress local_ip, IPAddress dns_server) { +/* -------------------------------------------------------------------------- */ + config(local_ip); + CLwipIf::getInstance().addDns(dns_server); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { +/* -------------------------------------------------------------------------- */ + IPAddress _nm(255, 255, 255, 0); + _config(local_ip, gateway, _nm); + CLwipIf::getInstance().addDns(dns_server); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { +/* -------------------------------------------------------------------------- */ + _config(local_ip, gateway, subnet); + CLwipIf::getInstance().addDns(dns_server); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::setDNS(IPAddress dns_server1) { +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().addDns(dns_server1); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().addDns(dns_server1); + CLwipIf::getInstance().addDns(dns_server2); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::setHostname(const char* name) { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// ni->setHostname(name); -// } -// } - -// /* -------------------------------------------------------------------------- */ -// int CWifi::disconnect() { -// /* -------------------------------------------------------------------------- */ -// CLwipIf::getInstance().disconnectFromAp(); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::end(void) { -// /* -------------------------------------------------------------------------- */ - -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t* CWifi::macAddress(uint8_t* mac) { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { -// return mac; -// } -// } -// memset(mac,0x00,6); -// return mac; -// } - -// /* -------------------------------------------------------------------------- */ -// int8_t CWifi::scanNetworks() { -// /* -------------------------------------------------------------------------- */ -// ni = CLwipIf::getInstance().get(NI_WIFI_STATION); -// if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { -// return CLwipIf::getInstance().getApNum(); -// } -// return 0; -// } +} + +/* -------------------------------------------------------------------------- */ +void CWifi::setHostname(const char* name) { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + ni->setHostname(name); + } +} + +/* -------------------------------------------------------------------------- */ +int CWifi::disconnect() { +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().disconnectFromAp(); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::end(void) { +/* -------------------------------------------------------------------------- */ + +} + +/* -------------------------------------------------------------------------- */ +uint8_t* CWifi::macAddress(uint8_t* mac) { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { + return mac; + } + } + memset(mac,0x00,6); + return mac; +} + +/* -------------------------------------------------------------------------- */ +int8_t CWifi::scanNetworks() { +/* -------------------------------------------------------------------------- */ + ni = CLwipIf::getInstance().get(NI_WIFI_STATION); + if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { + return CLwipIf::getInstance().getApNum(); + } + return 0; +} -// /* -------------------------------------------------------------------------- */ -// IPAddress CWifi::localIP() { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return IPAddress(ni->getIpAdd()); -// } -// return IPAddress((uint32_t)0); -// } - -// /* -------------------------------------------------------------------------- */ -// IPAddress CWifi::subnetMask() { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return IPAddress(ni->getNmAdd()); -// } -// return IPAddress((uint32_t)0); -// } - -// /* -------------------------------------------------------------------------- */ -// IPAddress CWifi::gatewayIP() { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return IPAddress(ni->getGwAdd()); -// } -// return IPAddress((uint32_t)0); -// } - -// /* -------------------------------------------------------------------------- */ -// IPAddress CWifi::dnsIP(int n) { -// return CLwipIf::getInstance().getDns(n); -// } - -// /* -------------------------------------------------------------------------- */ -// const char* CWifi::SSID(uint8_t networkItem) { -// return CLwipIf::getInstance().getSSID(networkItem); -// } -// /* -------------------------------------------------------------------------- */ - -// /* -------------------------------------------------------------------------- */ -// int32_t CWifi::RSSI(uint8_t networkItem) { -// return CLwipIf::getInstance().getRSSI(networkItem); -// } -// /* -------------------------------------------------------------------------- */ - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::encryptionType(uint8_t networkItem) { -// return CLwipIf::getInstance().getEncrType(networkItem); -// } -// /* -------------------------------------------------------------------------- */ - -// /* -------------------------------------------------------------------------- */ -// uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { -// return CLwipIf::getInstance().getBSSID(networkItem,bssid); -// } -// /* -------------------------------------------------------------------------- */ - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::channel(uint8_t networkItem) { -// return CLwipIf::getInstance().getChannel(networkItem); -// } -// /* -------------------------------------------------------------------------- */ - -// /* -------------------------------------------------------------------------- */ -// const char* CWifi::SSID() { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return ni->getSSID(); -// } -// return ""; -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t* CWifi::BSSID(uint8_t* bssid) { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return ni->getBSSID(bssid); -// } -// return nullptr; -// } - -// /* -------------------------------------------------------------------------- */ -// int32_t CWifi::RSSI() { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return ni->getRSSI(); -// } -// return 0; -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::encryptionType() { -// /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return ni->getEncryptionType(); -// } -// return 0; -// } - -// /* -------------------------------------------------------------------------- */ -// uint8_t CWifi::status() { -// /* -------------------------------------------------------------------------- */ -// return CLwipIf::getInstance().getWifiStatus(); -// } - -// /* -------------------------------------------------------------------------- */ -// int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { -// /* -------------------------------------------------------------------------- */ -// return CLwipIf::getInstance().getHostByName(aHostname,aResult); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::lowPowerMode() { -// /* -------------------------------------------------------------------------- */ -// CLwipIf::getInstance().setLowPowerMode(); -// } - -// /* -------------------------------------------------------------------------- */ -// void CWifi::noLowPowerMode() { -// /* -------------------------------------------------------------------------- */ -// CLwipIf::getInstance().resetLowPowerMode(); -// } - -// uint8_t CWifi::reasonCode() { -// return 0; -// } - -// unsigned long CWifi::getTime() { -// return 0; -// } - - - -// void CWifi::setTimeout(unsigned long timeout) { -// (void)(timeout); -// } - - -// CWifi WiFi; +/* -------------------------------------------------------------------------- */ +IPAddress CWifi::localIP() { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return IPAddress(ni->getIpAdd()); + } + return IPAddress((uint32_t)0); +} + +/* -------------------------------------------------------------------------- */ +IPAddress CWifi::subnetMask() { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return IPAddress(ni->getNmAdd()); + } + return IPAddress((uint32_t)0); +} + +/* -------------------------------------------------------------------------- */ +IPAddress CWifi::gatewayIP() { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return IPAddress(ni->getGwAdd()); + } + return IPAddress((uint32_t)0); +} + +/* -------------------------------------------------------------------------- */ +IPAddress CWifi::dnsIP(int n) { + return CLwipIf::getInstance().getDns(n); +} + +/* -------------------------------------------------------------------------- */ +const char* CWifi::SSID(uint8_t networkItem) { + return CLwipIf::getInstance().getSSID(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +int32_t CWifi::RSSI(uint8_t networkItem) { + return CLwipIf::getInstance().getRSSI(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::encryptionType(uint8_t networkItem) { + return CLwipIf::getInstance().getEncrType(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { + return CLwipIf::getInstance().getBSSID(networkItem,bssid); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::channel(uint8_t networkItem) { + return CLwipIf::getInstance().getChannel(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +const char* CWifi::SSID() { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getSSID(); + } + return ""; +} + +/* -------------------------------------------------------------------------- */ +uint8_t* CWifi::BSSID(uint8_t* bssid) { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getBSSID(bssid); + } + return nullptr; +} + +/* -------------------------------------------------------------------------- */ +int32_t CWifi::RSSI() { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getRSSI(); + } + return 0; +} + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::encryptionType() { +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getEncryptionType(); + } + return 0; +} + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::status() { +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().getWifiStatus(); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().getHostByName(aHostname,aResult); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::lowPowerMode() { +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().setLowPowerMode(); +} + +/* -------------------------------------------------------------------------- */ +void CWifi::noLowPowerMode() { +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().resetLowPowerMode(); +} + +uint8_t CWifi::reasonCode() { + return 0; +} + +unsigned long CWifi::getTime() { + return 0; +} + + + +void CWifi::setTimeout(unsigned long timeout) { + (void)(timeout); +} + + +CWifi WiFi; diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 3abde923..ffe55cbf 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -8,11 +8,7 @@ #define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" -#ifdef ARDUINO_PORTENTA_C33 // TODO Instantiate the drivers for wifi with default configuration parameters -// ESPHostFGDriver WifiDriver; // Instantiate a global variable from CWifiStation calling it WiFi -inline CWifiStation WiFi; -#endif // ARDUINO_PORTENTA_C33 From f20a25817207770b79aa23ab4e71156b9dd8964d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 5 Jan 2024 10:47:46 +0100 Subject: [PATCH 31/79] Revert "reimplementing wifi handle" This reverts commit d1e284b37c2c95d62d21bc6482571670ee2c89f1. --- libraries/WiFi/src/WiFiC3.h | 267 +++++++++++++++++++++++++++++++++++- 1 file changed, 260 insertions(+), 7 deletions(-) diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index ffe55cbf..2995cdcf 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -1,14 +1,267 @@ -#pragma once +#ifndef C_ARDUINO_WIFI_H +#define C_ARDUINO_WIFI_H #include "CNetIf.h" -#include "WiFiClient.h" -#include "WiFiServer.h" -#include "WiFiUdp.h" - #define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" -// TODO Instantiate the drivers for wifi with default configuration parameters +class CWifi { +private: + void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); + unsigned long _timeout; + bool _useStaticIp = false; + CNetIf *ni; + +public: + CWifi(); + + /* + * Get firmware version + */ + static const char* firmwareVersion(); + + + /* + * Start WiFi connection for OPEN networks + * param ssid: Pointer to the SSID string. + */ + int begin(const char* ssid); + + + + /* Start WiFi connection with passphrase + * the most secure supported mode will be automatically selected + * + * param ssid: Pointer to the SSID string. + * param passphrase: Passphrase. Valid characters in a passphrase + * must be between ASCII 32-126 (decimal). + */ + int begin(const char* ssid, const char *passphrase); + + /* connect as Access Point with a standard passphrase */ + uint8_t beginAP(const char *ssid); + uint8_t beginAP(const char *ssid, uint8_t channel); + uint8_t beginAP(const char *ssid, const char* passphrase); + uint8_t beginAP(const char *ssid, const char* passphrase, uint8_t channel); + + /* Change IP configuration settings disabling the DHCP client + * + * param local_ip: Static IP configuration + */ + void config(IPAddress local_ip); + + /* Change IP configuration settings disabling the DHCP client + * + * param local_ip: Static IP configuration + * param dns_server: IP configuration for DNS server 1 + */ + void config(IPAddress local_ip, IPAddress dns_server); + + /* Change IP configuration settings disabling the DHCP client + * + * param local_ip: Static IP configuration + * param dns_server: IP configuration for DNS server 1 + * param gateway : Static gateway configuration + */ + void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + + /* Change IP configuration settings disabling the DHCP client + * + * param local_ip: Static IP configuration + * param dns_server: IP configuration for DNS server 1 + * param gateway: Static gateway configuration + * param subnet: Static Subnet mask + */ + void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + + /* Change DNS IP configuration + * + * param dns_server1: IP configuration for DNS server 1 + */ + void setDNS(IPAddress dns_server1); + + /* Change DNS IP configuration + * + * param dns_server1: IP configuration for DNS server 1 + * param dns_server2: IP configuration for DNS server 2 + * + */ + void setDNS(IPAddress dns_server1, IPAddress dns_server2); + + + /* Set the hostname used for DHCP requests + * + * param name: hostname to set + * + */ + void setHostname(const char* name); + + /* + * Disconnect from the network + * + * return: one value of wl_status_t enum + */ + int disconnect(void); + + void end(void); + + /* + * Get the interface MAC address. + * + * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH + * + * the value returned by this function is meaningfull only if called + * afert a begin (both begin or beginAP) or a ScanNetwork function + * otherwise an empty mac address is returned + */ + uint8_t* macAddress(uint8_t* mac); + + /* + * Get the interface IP address. + * + * return: IP address value + */ + IPAddress localIP(); + + /* + * Get the interface subnet mask address. + * + * return: subnet mask address value + */ + IPAddress subnetMask(); + + /* + * Get the gateway IP address. + * + * return: gateway IP address value + */ + IPAddress gatewayIP(); + + /* + * Get the DNS server IP address. + * + * return: DNS server IP address value + */ + IPAddress dnsIP(int n = 0); -// Instantiate a global variable from CWifiStation calling it WiFi + /* + * Return the current SSID associated with the network + * + * return: ssid string + */ + const char* SSID(); + + /* + * Return the current BSSID associated with the network. + * It is the MAC address of the Access Point + * + * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH + */ + uint8_t* BSSID(uint8_t* bssid); + + /* + * Return the current RSSI/Received Signal Strength in dBm) + * associated with the network + * + * return: signed value + */ + int32_t RSSI(); + + /* + * Return the Encryption Type associated with the network + * + * return: one value of wl_enc_type enum + */ + uint8_t encryptionType(); + + /* + * Start scan WiFi networks available + * + * return: Number of discovered networks + */ + int8_t scanNetworks(); + + /* + * Return the SSID discovered during the network scan. + * + * param networkItem: specify from which network item want to get the information + * + * return: SSID string of the specified item on the networks scanned list + */ + const char* SSID(uint8_t networkItem); + + /* + * Return the encryption type of the networks discovered during the scanNetworks + * + * param networkItem: specify from which network item want to get the information + * + * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list + + enum wl_enc_type : + ENC_TYPE_WEP, + ENC_TYPE_WPA, + ENC_TYPE_WPA2, + ENC_TYPE_WPA2_ENTERPRISE, + ENC_TYPE_WPA3, + ENC_TYPE_NONE, + ENC_TYPE_AUTO, + + ENC_TYPE_UNKNOWN = 255 + + */ + uint8_t encryptionType(uint8_t networkItem); + + uint8_t* BSSID(uint8_t networkItem, uint8_t* bssid); + uint8_t channel(uint8_t networkItem); + + /* + * Return the RSSI of the networks discovered during the scanNetworks + * + * param networkItem: specify from which network item want to get the information + * + * return: signed value of RSSI of the specified item on the networks scanned list + */ + int32_t RSSI(uint8_t networkItem); + + /* + * Return Connection status. + * + * return: one of the value defined in wl_status_t + */ + uint8_t status(); + + /* + * Return The deauthentication reason code. + * + * return: the deauthentication reason code + */ + uint8_t reasonCode(); + + /* + * Resolve the given hostname to an IP address. + * param aHostname: Name to be resolved + * param aResult: IPAddress structure to store the returned IP address + * result: 1 if aIPAddrString was successfully converted to an IP address, + * else error code + */ + int hostByName(const char* aHostname, IPAddress& aResult); + + unsigned long getTime(); + + void lowPowerMode(); + void noLowPowerMode(); + + + + void setTimeout(unsigned long timeout); + + +}; + +extern CWifi WiFi; + +#include "WiFiClient.h" +#include "WiFiServer.h" +#include "WiFiUdp.h" +#endif From 552a15309139f8075a7edf09c6490be5dc089d78 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 5 Jan 2024 11:01:10 +0100 Subject: [PATCH 32/79] applying a codestyle --- libraries/WiFi/src/WiFi.cpp | 314 ++++++++++++++++++------------------ libraries/WiFi/src/WiFiC3.h | 101 ++++++------ 2 files changed, 198 insertions(+), 217 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 59e742a0..4dda14ac 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -12,320 +12,312 @@ CWifi::CWifi() : _timeout(50000), ni(nullptr) { /* -------------------------------------------------------------------------- */ const char* CWifi::firmwareVersion() { -/* -------------------------------------------------------------------------- */ - /* silly "dummy" implementation to keep compatibility, at the present +/* -------------------------------------------------------------------------- */ + /* silly "dummy" implementation to keep compatibility, at the present the WiFi fw does not return any version number */ - return WIFI_FIRMWARE_LATEST_VERSION; + return WIFI_FIRMWARE_LATEST_VERSION; } /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid) { -/* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); - CLwipIf::getInstance().connectToAp(ssid, nullptr); - if(ni != nullptr && !_useStaticIp) { - ni->DhcpStart(); - } - - return CLwipIf::getInstance().getWifiStatus(); +/* -------------------------------------------------------------------------- */ + ni = CLwipIf::getInstance().get(NI_WIFI_STATION); // FIXME + CLwipIf::getInstance().connectToAp(ssid, nullptr); // FIXME + if(ni != nullptr && !_useStaticIp) { + ni->DhcpStart(); + } + + return CLwipIf::getInstance().getWifiStatus(); // FIXME } /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid, const char *passphrase) { -/* -------------------------------------------------------------------------- */ - - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); - CLwipIf::getInstance().connectToAp(ssid, passphrase); - if(ni != nullptr && !_useStaticIp) { - ni->DhcpStart(); - } - - return CLwipIf::getInstance().getWifiStatus(); +/* -------------------------------------------------------------------------- */ + ni = CLwipIf::getInstance().get(NI_WIFI_STATION); // FIXME + CLwipIf::getInstance().connectToAp(ssid, passphrase); // FIXME + if(ni != nullptr && !_useStaticIp) { + ni->DhcpStart(); + } + + return CLwipIf::getInstance().getWifiStatus(); // FIXME } /* passphrase is needed so a default one will be set */ /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid) { -/* -------------------------------------------------------------------------- */ - return beginAP(ssid,1); +/* -------------------------------------------------------------------------- */ + return beginAP(ssid,1); } /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, uint8_t channel) { -/* -------------------------------------------------------------------------- */ - return beginAP(ssid,nullptr,channel); +/* -------------------------------------------------------------------------- */ + return beginAP(ssid,nullptr,channel); } /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { -/* -------------------------------------------------------------------------- */ - return beginAP(ssid,passphrase,1); +/* -------------------------------------------------------------------------- */ + return beginAP(ssid,passphrase,1); } /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { -/* -------------------------------------------------------------------------- */ - - ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); - CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); - if(ni != nullptr) { - - dhcps_start(ni->getNi()); - } - - return CLwipIf::getInstance().getWifiStatus(); +/* -------------------------------------------------------------------------- */ + ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); // FIXME + CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); // FIXME + if(ni != nullptr) { + dhcps_start(ni->getNi()); + } + + return CLwipIf::getInstance().getWifiStatus(); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip) { -/* -------------------------------------------------------------------------- */ - IPAddress _nm(255, 255, 255, 0); - IPAddress _gw = local_ip; - _gw[3] = 1; +/* -------------------------------------------------------------------------- */ + IPAddress _nm(255, 255, 255, 0); + IPAddress _gw = local_ip; + _gw[3] = 1; - _config(local_ip, _gw, _nm); + _config(local_ip, _gw, _nm); } extern uint8_t *IpAddress2uint8(IPAddress a); /* -------------------------------------------------------------------------- */ void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { -/* -------------------------------------------------------------------------- */ - _useStaticIp = local_ip != INADDR_NONE; - if(ni != nullptr) { - ni->DhcpStop(); - ni->DhcpNotUsed(); - IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); - IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); - IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); - } - else { - CNetIf::default_ip = local_ip; - CNetIf::default_nm = subnet; - CNetIf::default_gw = gateway; - CNetIf::default_dhcp_server_ip = local_ip; - } +/* -------------------------------------------------------------------------- */ + _useStaticIp = local_ip != INADDR_NONE; + if(ni != nullptr) { + ni->DhcpStop(); + ni->DhcpNotUsed(); + IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); + IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); + IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); + } + else { + CNetIf::default_ip = local_ip; + CNetIf::default_nm = subnet; + CNetIf::default_gw = gateway; + CNetIf::default_dhcp_server_ip = local_ip; + } } /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip, IPAddress dns_server) { -/* -------------------------------------------------------------------------- */ - config(local_ip); - CLwipIf::getInstance().addDns(dns_server); +/* -------------------------------------------------------------------------- */ + config(local_ip); + CLwipIf::getInstance().addDns(dns_server); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) { -/* -------------------------------------------------------------------------- */ - IPAddress _nm(255, 255, 255, 0); - _config(local_ip, gateway, _nm); - CLwipIf::getInstance().addDns(dns_server); +/* -------------------------------------------------------------------------- */ + IPAddress _nm(255, 255, 255, 0); + _config(local_ip, gateway, _nm); + CLwipIf::getInstance().addDns(dns_server); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { /* -------------------------------------------------------------------------- */ - _config(local_ip, gateway, subnet); - CLwipIf::getInstance().addDns(dns_server); + _config(local_ip, gateway, subnet); + CLwipIf::getInstance().addDns(dns_server); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server1); +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().addDns(dns_server1); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server1); - CLwipIf::getInstance().addDns(dns_server2); - +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().addDns(dns_server1); // FIXME + CLwipIf::getInstance().addDns(dns_server2); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::setHostname(const char* name) { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - ni->setHostname(name); - } +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + ni->setHostname(name); + } } /* -------------------------------------------------------------------------- */ int CWifi::disconnect() { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().disconnectFromAp(); +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().disconnectFromAp(); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::end(void) { -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ } /* -------------------------------------------------------------------------- */ uint8_t* CWifi::macAddress(uint8_t* mac) { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { - return mac; - } - } - memset(mac,0x00,6); - return mac; +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { + return mac; + } + } + memset(mac,0x00,6); + return mac; } /* -------------------------------------------------------------------------- */ int8_t CWifi::scanNetworks() { -/* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); - if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { - return CLwipIf::getInstance().getApNum(); - } - return 0; -} - -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + ni = CLwipIf::getInstance().get(NI_WIFI_STATION); // FIXME + if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { // FIXME + return CLwipIf::getInstance().getApNum(); // FIXME + } + return 0; +} + +/* -------------------------------------------------------------------------- */ IPAddress CWifi::localIP() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getIpAdd()); - } - return IPAddress((uint32_t)0); +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return IPAddress(ni->getIpAdd()); + } + return IPAddress((uint32_t)0); } /* -------------------------------------------------------------------------- */ IPAddress CWifi::subnetMask() { /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getNmAdd()); - } - return IPAddress((uint32_t)0); + if(ni != nullptr) { + return IPAddress(ni->getNmAdd()); + } + return IPAddress((uint32_t)0); } /* -------------------------------------------------------------------------- */ IPAddress CWifi::gatewayIP() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getGwAdd()); - } - return IPAddress((uint32_t)0); +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return IPAddress(ni->getGwAdd()); + } + return IPAddress((uint32_t)0); } /* -------------------------------------------------------------------------- */ IPAddress CWifi::dnsIP(int n) { - return CLwipIf::getInstance().getDns(n); + return CLwipIf::getInstance().getDns(n); // FIXME } /* -------------------------------------------------------------------------- */ -const char* CWifi::SSID(uint8_t networkItem) { - return CLwipIf::getInstance().getSSID(networkItem); +const char* CWifi::SSID(uint8_t networkItem) { + return CLwipIf::getInstance().getSSID(networkItem); // FIXME } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int32_t CWifi::RSSI(uint8_t networkItem) { - return CLwipIf::getInstance().getRSSI(networkItem); + return CLwipIf::getInstance().getRSSI(networkItem); // FIXME } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ uint8_t CWifi::encryptionType(uint8_t networkItem) { - return CLwipIf::getInstance().getEncrType(networkItem); + return CLwipIf::getInstance().getEncrType(networkItem); // FIXME } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { - return CLwipIf::getInstance().getBSSID(networkItem,bssid); + return CLwipIf::getInstance().getBSSID(networkItem,bssid); // FIXME } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t CWifi::channel(uint8_t networkItem) { - return CLwipIf::getInstance().getChannel(networkItem); +uint8_t CWifi::channel(uint8_t networkItem) { + return CLwipIf::getInstance().getChannel(networkItem); // FIXME } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ const char* CWifi::SSID() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getSSID(); - } - return ""; +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getSSID(); + } + return ""; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ uint8_t* CWifi::BSSID(uint8_t* bssid) { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getBSSID(bssid); - } - return nullptr; +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getBSSID(bssid); + } + return nullptr; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ int32_t CWifi::RSSI() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getRSSI(); - } - return 0; +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getRSSI(); + } + return 0; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ uint8_t CWifi::encryptionType() { -/* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getEncryptionType(); - } - return 0; +/* -------------------------------------------------------------------------- */ + if(ni != nullptr) { + return ni->getEncryptionType(); + } + return 0; } /* -------------------------------------------------------------------------- */ uint8_t CWifi::status() { -/* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getWifiStatus(); +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().getWifiStatus(); // FIXME } /* -------------------------------------------------------------------------- */ int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { -/* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getHostByName(aHostname,aResult); +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().getHostByName(aHostname,aResult); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::lowPowerMode() { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().setLowPowerMode(); +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().setLowPowerMode(); // FIXME } /* -------------------------------------------------------------------------- */ void CWifi::noLowPowerMode() { -/* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().resetLowPowerMode(); +/* -------------------------------------------------------------------------- */ + CLwipIf::getInstance().resetLowPowerMode(); // FIXME } uint8_t CWifi::reasonCode() { - return 0; + return 0; } unsigned long CWifi::getTime() { - return 0; + return 0; } void CWifi::setTimeout(unsigned long timeout) { - (void)(timeout); + (void)(timeout); } - - -CWifi WiFi; - diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 2995cdcf..2080e538 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -1,17 +1,14 @@ -#ifndef C_ARDUINO_WIFI_H -#define C_ARDUINO_WIFI_H +#pragma once #include "CNetIf.h" #define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" class CWifi { -private: - void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); - unsigned long _timeout; - bool _useStaticIp = false; - CNetIf *ni; - +private: + void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); + unsigned long _timeout; + bool _useStaticIp = false; public: CWifi(); @@ -21,14 +18,12 @@ class CWifi { static const char* firmwareVersion(); - /* - * Start WiFi connection for OPEN networks + /* + * Start WiFi connection for OPEN networks * param ssid: Pointer to the SSID string. */ int begin(const char* ssid); - - /* Start WiFi connection with passphrase * the most secure supported mode will be automatically selected * @@ -51,29 +46,29 @@ class CWifi { void config(IPAddress local_ip); /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - * param dns_server: IP configuration for DNS server 1 - */ + * + * param local_ip: Static IP configuration + * param dns_server: IP configuration for DNS server 1 + */ void config(IPAddress local_ip, IPAddress dns_server); /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - * param dns_server: IP configuration for DNS server 1 - * param gateway : Static gateway configuration - */ + * + * param local_ip: Static IP configuration + * param dns_server: IP configuration for DNS server 1 + * param gateway : Static gateway configuration + */ void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); /* Change IP configuration settings disabling the DHCP client - * - * param local_ip: Static IP configuration - * param dns_server: IP configuration for DNS server 1 - * param gateway: Static gateway configuration - * param subnet: Static Subnet mask - */ + * + * param local_ip: Static IP configuration + * param dns_server: IP configuration for DNS server 1 + * param gateway: Static gateway configuration + * param subnet: Static Subnet mask + */ void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); - + /* Change DNS IP configuration * * param dns_server1: IP configuration for DNS server 1 @@ -109,8 +104,8 @@ class CWifi { * Get the interface MAC address. * * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH - * - * the value returned by this function is meaningfull only if called + * + * the value returned by this function is meaningfull only if called * afert a begin (both begin or beginAP) or a ScanNetwork function * otherwise an empty mac address is returned */ @@ -135,14 +130,14 @@ class CWifi { * * return: gateway IP address value */ - IPAddress gatewayIP(); + IPAddress gatewayIP(); - /* - * Get the DNS server IP address. - * - * return: DNS server IP address value - */ - IPAddress dnsIP(int n = 0); + /* + * Get the DNS server IP address. + * + * return: DNS server IP address value + */ + IPAddress dnsIP(int n = 0); /* * Return the current SSID associated with the network @@ -194,20 +189,20 @@ class CWifi { * Return the encryption type of the networks discovered during the scanNetworks * * param networkItem: specify from which network item want to get the information - * + * * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list - enum wl_enc_type : - ENC_TYPE_WEP, - ENC_TYPE_WPA, - ENC_TYPE_WPA2, - ENC_TYPE_WPA2_ENTERPRISE, - ENC_TYPE_WPA3, - ENC_TYPE_NONE, - ENC_TYPE_AUTO, - - ENC_TYPE_UNKNOWN = 255 - + * enum wl_enc_type : + * ENC_TYPE_WEP, + * ENC_TYPE_WPA, + * ENC_TYPE_WPA2, + * ENC_TYPE_WPA2_ENTERPRISE, + * ENC_TYPE_WPA3, + * ENC_TYPE_NONE, + * ENC_TYPE_AUTO, + * + * ENC_TYPE_UNKNOWN = 255 + * */ uint8_t encryptionType(uint8_t networkItem); @@ -251,17 +246,11 @@ class CWifi { void lowPowerMode(); void noLowPowerMode(); - - void setTimeout(unsigned long timeout); - - }; -extern CWifi WiFi; +inline CWifi WiFi; #include "WiFiClient.h" #include "WiFiServer.h" #include "WiFiUdp.h" - -#endif From d2395979254f5c4735964b040cc02837a01274f6 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 10:24:32 +0100 Subject: [PATCH 33/79] fixing EthernetServer class --- libraries/Ethernet/src/EthernetServer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/EthernetServer.h b/libraries/Ethernet/src/EthernetServer.h index 302af571..1dbf791d 100644 --- a/libraries/Ethernet/src/EthernetServer.h +++ b/libraries/Ethernet/src/EthernetServer.h @@ -5,9 +5,10 @@ class EthernetServer: public lwipServer { public: + EthernetServer(uint16_t port) : lwipServer(port) {} void begin() { lwipServer::begin(); - this->bindCNetIf(WiFi); + this->bindCNetIf(Ethernet); } EthernetClient available() { From 6e6c8376e92ebf9c4e298f35ca695bd3706dfb1e Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 10:25:14 +0100 Subject: [PATCH 34/79] making WiFi class compile --- libraries/WiFi/src/WiFi.cpp | 234 +++++++++++++++++------------------- libraries/WiFi/src/WiFiC3.h | 8 ++ 2 files changed, 116 insertions(+), 126 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 4dda14ac..6535732b 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -6,7 +6,7 @@ extern "C" void dhcps_start(struct netif *netif); /* -------------------------------------------------------------------------- */ -CWifi::CWifi() : _timeout(50000), ni(nullptr) { +CWifi::CWifi() : _timeout(50000) { } /* -------------------------------------------------------------------------- */ @@ -23,97 +23,85 @@ const char* CWifi::firmwareVersion() { /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid) { /* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); // FIXME - CLwipIf::getInstance().connectToAp(ssid, nullptr); // FIXME - if(ni != nullptr && !_useStaticIp) { - ni->DhcpStart(); - } - - return CLwipIf::getInstance().getWifiStatus(); // FIXME + WiFiStation.begin(); + return WiFiStation.connectToAP(ssid, nullptr); } /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid, const char *passphrase) { /* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); // FIXME - CLwipIf::getInstance().connectToAp(ssid, passphrase); // FIXME - if(ni != nullptr && !_useStaticIp) { - ni->DhcpStart(); - } - - return CLwipIf::getInstance().getWifiStatus(); // FIXME + WiFiStation.begin(); + return WiFiStation.connectToAP(ssid, passphrase); } /* passphrase is needed so a default one will be set */ /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid) { /* -------------------------------------------------------------------------- */ - return beginAP(ssid,1); + WiFiSoftAP.begin(); + return WiFiSoftAP.startSoftAp(ssid); // FIXME put default password here } /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, uint8_t channel) { /* -------------------------------------------------------------------------- */ - return beginAP(ssid,nullptr,channel); + WiFiSoftAP.begin(); + return WiFiSoftAP.startSoftAp(ssid, nullptr, channel); } /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase) { /* -------------------------------------------------------------------------- */ - return beginAP(ssid,passphrase,1); + WiFiSoftAP.begin(); + return WiFiSoftAP.startSoftAp(ssid, passphrase); } /* -------------------------------------------------------------------------- */ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel) { /* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_SOFTAP); // FIXME - CLwipIf::getInstance().startSoftAp(ssid,passphrase,channel); // FIXME - if(ni != nullptr) { - dhcps_start(ni->getNi()); - } - - return CLwipIf::getInstance().getWifiStatus(); // FIXME + WiFiSoftAP.begin(); + return WiFiSoftAP.startSoftAp(ssid, passphrase, channel); } /* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip) { +void CWifi::config(IPAddress local_ip) { // FIXME /* -------------------------------------------------------------------------- */ - IPAddress _nm(255, 255, 255, 0); - IPAddress _gw = local_ip; - _gw[3] = 1; + // IPAddress _nm(255, 255, 255, 0); + // IPAddress _gw = local_ip; + // _gw[3] = 1; - _config(local_ip, _gw, _nm); + // _config(local_ip, _gw, _nm); } extern uint8_t *IpAddress2uint8(IPAddress a); /* -------------------------------------------------------------------------- */ -void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { +void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { // FIXME /* -------------------------------------------------------------------------- */ - _useStaticIp = local_ip != INADDR_NONE; - if(ni != nullptr) { - ni->DhcpStop(); - ni->DhcpNotUsed(); - IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); - IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); - IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); - } - else { - CNetIf::default_ip = local_ip; - CNetIf::default_nm = subnet; - CNetIf::default_gw = gateway; - CNetIf::default_dhcp_server_ip = local_ip; - } + // _useStaticIp = local_ip != INADDR_NONE; + // if(ni != nullptr) { + // ni->DhcpStop(); + // ni->DhcpNotUsed(); + // IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); + // IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); + // IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); + // } + // else { + // CNetIf::default_ip = local_ip; + // CNetIf::default_nm = subnet; + // CNetIf::default_gw = gateway; + // CNetIf::default_dhcp_server_ip = local_ip; + // } } /* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip, IPAddress dns_server) { +void CWifi::config(IPAddress local_ip, IPAddress dns_server) { // FIXME /* -------------------------------------------------------------------------- */ config(local_ip); - CLwipIf::getInstance().addDns(dns_server); // FIXME + // CLwipIf::getInstance().addDns(dns_server); } /* -------------------------------------------------------------------------- */ @@ -121,41 +109,41 @@ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) /* -------------------------------------------------------------------------- */ IPAddress _nm(255, 255, 255, 0); _config(local_ip, gateway, _nm); - CLwipIf::getInstance().addDns(dns_server); // FIXME + // CLwipIf::getInstance().addDns(dns_server); } /* -------------------------------------------------------------------------- */ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { /* -------------------------------------------------------------------------- */ _config(local_ip, gateway, subnet); - CLwipIf::getInstance().addDns(dns_server); // FIXME + // CLwipIf::getInstance().addDns(dns_server); } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1) { /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server1); // FIXME + // CLwipIf::getInstance().addDns(dns_server1); } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().addDns(dns_server1); // FIXME - CLwipIf::getInstance().addDns(dns_server2); // FIXME + // CLwipIf::getInstance().addDns(dns_server1); + // CLwipIf::getInstance().addDns(dns_server2); } /* -------------------------------------------------------------------------- */ void CWifi::setHostname(const char* name) { /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - ni->setHostname(name); - } +// if(ni != nullptr) { +// ni->setHostname(name); +// } } /* -------------------------------------------------------------------------- */ int CWifi::disconnect() { /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().disconnectFromAp(); // FIXME + WiFiStation.disconnectFromAp(); } /* -------------------------------------------------------------------------- */ @@ -165,147 +153,143 @@ void CWifi::end(void) { } /* -------------------------------------------------------------------------- */ -uint8_t* CWifi::macAddress(uint8_t* mac) { +uint8_t* CWifi::macAddress(uint8_t* mac) { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { - return mac; - } - } - memset(mac,0x00,6); - return mac; +// if(ni != nullptr) { +// if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { +// return mac; +// } +// } +// memset(mac,0x00,6); +// return mac; } /* -------------------------------------------------------------------------- */ int8_t CWifi::scanNetworks() { /* -------------------------------------------------------------------------- */ - ni = CLwipIf::getInstance().get(NI_WIFI_STATION); // FIXME - if(CLwipIf::getInstance().scanForAp() == ESP_CONTROL_OK) { // FIXME - return CLwipIf::getInstance().getApNum(); // FIXME - } - return 0; + return WiFiStation.scanForAp();; } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::localIP() { +IPAddress CWifi::localIP() { //FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getIpAdd()); - } - return IPAddress((uint32_t)0); + // if(ni != nullptr) { + // return IPAddress(ni->getIpAdd()); + // } + // return IPAddress((uint32_t)0); } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::subnetMask() { +IPAddress CWifi::subnetMask() { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getNmAdd()); - } - return IPAddress((uint32_t)0); +// if(ni != nullptr) { +// return IPAddress(ni->getNmAdd()); +// } +// return IPAddress((uint32_t)0); } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::gatewayIP() { +IPAddress CWifi::gatewayIP() { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return IPAddress(ni->getGwAdd()); - } - return IPAddress((uint32_t)0); + // if(ni != nullptr) { + // return IPAddress(ni->getGwAdd()); + // } + // return IPAddress((uint32_t)0); } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::dnsIP(int n) { - return CLwipIf::getInstance().getDns(n); // FIXME +IPAddress CWifi::dnsIP(int n) { // FIXME + // return CLwipIf::getInstance().getDns(n); } /* -------------------------------------------------------------------------- */ -const char* CWifi::SSID(uint8_t networkItem) { - return CLwipIf::getInstance().getSSID(networkItem); // FIXME +const char* CWifi::SSID(uint8_t networkItem) { // FIXME + // return CLwipIf::getInstance().getSSID(networkItem); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int32_t CWifi::RSSI(uint8_t networkItem) { - return CLwipIf::getInstance().getRSSI(networkItem); // FIXME +int32_t CWifi::RSSI(uint8_t networkItem) { // FIXME + // return CLwipIf::getInstance().getRSSI(networkItem); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t CWifi::encryptionType(uint8_t networkItem) { - return CLwipIf::getInstance().getEncrType(networkItem); // FIXME +uint8_t CWifi::encryptionType(uint8_t networkItem) { // FIXME + // return CLwipIf::getInstance().getEncrType(networkItem); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { - return CLwipIf::getInstance().getBSSID(networkItem,bssid); // FIXME +uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { // FIXME + // return CLwipIf::getInstance().getBSSID(networkItem,bssid); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t CWifi::channel(uint8_t networkItem) { - return CLwipIf::getInstance().getChannel(networkItem); // FIXME +uint8_t CWifi::channel(uint8_t networkItem) { // FIXME + // return CLwipIf::getInstance().getChannel(networkItem); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -const char* CWifi::SSID() { +const char* CWifi::SSID() { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getSSID(); - } - return ""; + // if(ni != nullptr) { + // return ni->getSSID(); + // } + // return ""; } /* -------------------------------------------------------------------------- */ -uint8_t* CWifi::BSSID(uint8_t* bssid) { +uint8_t* CWifi::BSSID(uint8_t* bssid) { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getBSSID(bssid); - } - return nullptr; + // if(ni != nullptr) { + // return ni->getBSSID(bssid); + // } + // return nullptr; } /* -------------------------------------------------------------------------- */ -int32_t CWifi::RSSI() { +int32_t CWifi::RSSI() { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getRSSI(); - } - return 0; + // if(ni != nullptr) { + // return ni->getRSSI(); + // } + // return 0; } /* -------------------------------------------------------------------------- */ -uint8_t CWifi::encryptionType() { +uint8_t CWifi::encryptionType() { // FIXME /* -------------------------------------------------------------------------- */ - if(ni != nullptr) { - return ni->getEncryptionType(); - } - return 0; + // if(ni != nullptr) { + // return ni->getEncryptionType(); + // } + // return 0; } /* -------------------------------------------------------------------------- */ -uint8_t CWifi::status() { +uint8_t CWifi::status() { // FIXME /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getWifiStatus(); // FIXME + // return CLwipIf::getInstance().getWifiStatus(); } /* -------------------------------------------------------------------------- */ -int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { +int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { // FIXME /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().getHostByName(aHostname,aResult); // FIXME + // return CLwipIf::getInstance().getHostByName(aHostname,aResult); } /* -------------------------------------------------------------------------- */ -void CWifi::lowPowerMode() { +void CWifi::lowPowerMode() { // FIXME /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().setLowPowerMode(); // FIXME + // CLwipIf::getInstance().setLowPowerMode(); } /* -------------------------------------------------------------------------- */ -void CWifi::noLowPowerMode() { +void CWifi::noLowPowerMode() { // FIXME /* -------------------------------------------------------------------------- */ - CLwipIf::getInstance().resetLowPowerMode(); // FIXME + // CLwipIf::getInstance().resetLowPowerMode(); } uint8_t CWifi::reasonCode() { @@ -316,8 +300,6 @@ unsigned long CWifi::getTime() { return 0; } - - void CWifi::setTimeout(unsigned long timeout) { (void)(timeout); } diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 2080e538..9192028e 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -4,6 +4,14 @@ #define WIFI_FIRMWARE_LATEST_VERSION "1.5.0" +// TODO Instantiate the drivers for wifi with default configuration parameters +// ESPHostFGDriver WifiDriver; + +// Instantiate a global variable from CWifiStation calling it WiFi + +inline CWifiStation WiFiStation; +inline CWifiSoftAp WiFiSoftAP; + class CWifi { private: void _config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); From ea4ae60d7588c40853efaa78a282f37a0d1ef968 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 10:25:56 +0100 Subject: [PATCH 35/79] fixing implementation of client and server --- libraries/WiFi/src/WiFiClient.h | 2 +- libraries/WiFi/src/WiFiServer.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index 98761c51..29d229ee 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -16,7 +16,7 @@ class WiFiClient: public lwipClient { int connect(IPAddress ip, uint16_t port) { auto res = lwipClient::connect(ip, port); - this->bindCNetIf(WiFi); + this->bindCNetIf(WiFiStation); return res; } diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index c72c8659..c6d6a35f 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -5,9 +5,10 @@ class WiFiServer: public lwipServer { public: + WiFiServer(uint16_t port) : lwipServer(port) {} void begin() { lwipServer::begin(); - this->bindCNetIf(WiFi); + this->bindCNetIf(WiFiStation); } WiFiClient available() { From 87ae27a0b94d3922d4a968bb40606f06fceae33f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 10:26:28 +0100 Subject: [PATCH 36/79] fixing global definitions of WiFi interfaces --- libraries/lwIpWrapper/src/CNetIf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 8c96f1fe..0f7b421a 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -280,7 +280,6 @@ class CWifiSoftAp : public CNetIf { virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); - virtual int32_t getRSSI(); virtual uint8_t getEncryptionType(); protected: static const char softap_ifname_prefix = 's'; @@ -358,4 +357,5 @@ class CLwipIf { }; extern CEth Ethernet; -extern CWifiStation WiFi; \ No newline at end of file +extern CWifiStation WiFiStation; +extern CWifiSoftAp WiFiSoftAP; From 0c210ee25478e4ef1a5fd0094e3bc0cd49e4aa31 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 10:46:33 +0100 Subject: [PATCH 37/79] making UDP derived classes compile --- libraries/Ethernet/src/EthernetUdp.h | 2 +- libraries/WiFi/src/WiFiUdp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Ethernet/src/EthernetUdp.h b/libraries/Ethernet/src/EthernetUdp.h index 0d450b76..21f5f6b7 100644 --- a/libraries/Ethernet/src/EthernetUdp.h +++ b/libraries/Ethernet/src/EthernetUdp.h @@ -10,7 +10,7 @@ class EthernetUDP : public lwipUDP { public: EthernetUDP() {} virtual uint8_t begin(uint16_t port) override { - CNetIf *ni = CLwipIf::getInstance().get(NI_ETHERNET); + CNetIf *ni = &Ethernet; if(ni != nullptr) { return lwipUDP::begin(IPAddress(ni->getIpAdd()), port); } diff --git a/libraries/WiFi/src/WiFiUdp.h b/libraries/WiFi/src/WiFiUdp.h index 4b0f3531..f9eb8c3d 100644 --- a/libraries/WiFi/src/WiFiUdp.h +++ b/libraries/WiFi/src/WiFiUdp.h @@ -8,7 +8,7 @@ class WiFiUDP : public lwipUDP { public: WiFiUDP() {} virtual uint8_t begin(uint16_t port) override { - CNetIf *ni = CLwipIf::getInstance().get(NI_WIFI_STATION); + CNetIf *ni = &WiFiStation; if(ni != nullptr) { return lwipUDP::begin(IPAddress(ni->getIpAdd()), port); } From 2c10e0edbfddc7cf4779ebb9fe327da9b5029a3e Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 13:34:46 +0100 Subject: [PATCH 38/79] fixing retrocompatibility issues --- libraries/WiFi/src/WiFi.cpp | 3 +++ libraries/lwIpWrapper/src/CNetIf.h | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 6535732b..e96d58d4 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -177,6 +177,7 @@ IPAddress CWifi::localIP() { //FIXME // return IPAddress(ni->getIpAdd()); // } // return IPAddress((uint32_t)0); + return WiFiStation.localIP(); } /* -------------------------------------------------------------------------- */ @@ -186,6 +187,7 @@ IPAddress CWifi::subnetMask() { // FIXME // return IPAddress(ni->getNmAdd()); // } // return IPAddress((uint32_t)0); + return WiFiStation.subnetMask(); } /* -------------------------------------------------------------------------- */ @@ -195,6 +197,7 @@ IPAddress CWifi::gatewayIP() { // FIXME // return IPAddress(ni->getGwAdd()); // } // return IPAddress((uint32_t)0); + return WiFiStation.gatewayIP(); } /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 0f7b421a..75ca27d2 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -148,6 +148,13 @@ class CNetIf: public NetworkInterface { uint32_t getNmAdd() { return ip4_addr_get_u32(&(ni.netmask)); } uint32_t getGwAdd() { return ip4_addr_get_u32(&(ni.gw)); } + // FIXME when dhcp has not provided an ip address yet return IPADDR_NONE + IPAddress localIP() { return IPAddress(this->getIpAdd()); } + IPAddress subnetMask() { return IPAddress(this->getNmAdd()); } + IPAddress gatewayIP() { return IPAddress(this->getGwAdd()); } + IPAddress dnsServerIP() { /* FIXME understand where dns should be managed */} + + // FIXME hostname should be defined in the NetworkStack singleton // void setHostname(const char* name) // { // memset(hostname, 0x00, MAX_HOSTNAME_DIM); From 4cb8171f94afc81f40ae1cf1c02f6b78e7f7ac25 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 8 Jan 2024 14:09:21 +0100 Subject: [PATCH 39/79] dealing with retrocompatibility --- libraries/lwIpWrapper/src/CNetIf.cpp | 5 +++-- libraries/lwIpWrapper/src/CNetIf.h | 12 +++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index c6668a63..f090f8e5 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -428,7 +428,7 @@ CEth::CEth(NetworkDriver *driver) // driver.stats = &this->stats; } -int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { +int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw, const IPAddress &dns) { // The driver needs a callback to consume the incoming buffer this->driver->setConsumeCallback( std::bind(&CEth::consume_callback, @@ -438,10 +438,11 @@ int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { CNetIf::begin(ip, nm, gw); netif_set_link_up(&this->ni); // TODO test that moving this here still makes ethernet work + // TODO set dns server + return 0; } - err_t CEth::init(struct netif* ni) { // Setting up netif #if LWIP_NETIF_HOSTNAME diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 75ca27d2..fd2fbe5a 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -202,12 +202,22 @@ class CEth : public CNetIf { virtual int begin( const IPAddress &ip = INADDR_NONE, const IPAddress &nm = INADDR_NONE, - const IPAddress &gw = INADDR_NONE) override; + const IPAddress &gw = INADDR_NONE, + const IPAddress &dns = INADDR_NONE); + + // virtual int begin( + // const IPAddress &ip = INADDR_NONE, + // const IPAddress &nm = INADDR_NONE, + // const IPAddress &gw = INADDR_NONE, + // const IPAddress &dns = INADDR_NONE); virtual int getMacAddress(uint8_t* mac) override { UNUSED(mac); // FIXME not implemented return 1; } + + int maintain() {} // Deprecated method for retrocompatibility + void schedule(void) {} // Deprecated method for retrocompatibility protected: /* * this function is used to initialize the netif structure of lwip From c9ed50ccf001e40788508d3ad3665036a4a4dc2f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 9 Jan 2024 16:12:27 +0100 Subject: [PATCH 40/79] solving FIXME --- libraries/WiFi/src/WiFi.cpp | 104 +++++++----------------- libraries/WiFi/src/WiFiC3.h | 42 +--------- libraries/lwIpWrapper/src/CNetIf.cpp | 116 +++++++++++++-------------- libraries/lwIpWrapper/src/CNetIf.h | 24 ++++-- 4 files changed, 102 insertions(+), 184 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index e96d58d4..1be48463 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -153,15 +153,13 @@ void CWifi::end(void) { } /* -------------------------------------------------------------------------- */ -uint8_t* CWifi::macAddress(uint8_t* mac) { // FIXME +uint8_t* CWifi::macAddress(uint8_t* mac) { /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// if(ni->getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { -// return mac; -// } -// } -// memset(mac,0x00,6); -// return mac; + if(WiFiStation.getMacAddress(mac) == WL_MAC_ADDR_LENGTH) { + return mac; + } + memset(mac,0x00,6); + return mac; } /* -------------------------------------------------------------------------- */ @@ -171,105 +169,57 @@ int8_t CWifi::scanNetworks() { } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::localIP() { //FIXME +IPAddress CWifi::localIP() { /* -------------------------------------------------------------------------- */ - // if(ni != nullptr) { - // return IPAddress(ni->getIpAdd()); - // } - // return IPAddress((uint32_t)0); return WiFiStation.localIP(); } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::subnetMask() { // FIXME +IPAddress CWifi::subnetMask() { /* -------------------------------------------------------------------------- */ -// if(ni != nullptr) { -// return IPAddress(ni->getNmAdd()); -// } -// return IPAddress((uint32_t)0); return WiFiStation.subnetMask(); } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::gatewayIP() { // FIXME +IPAddress CWifi::gatewayIP() { /* -------------------------------------------------------------------------- */ - // if(ni != nullptr) { - // return IPAddress(ni->getGwAdd()); - // } - // return IPAddress((uint32_t)0); return WiFiStation.gatewayIP(); } /* -------------------------------------------------------------------------- */ -IPAddress CWifi::dnsIP(int n) { // FIXME - // return CLwipIf::getInstance().getDns(n); +IPAddress CWifi::dnsIP(int n) { + return CLwipIf::getInstance().getDns(n); } /* -------------------------------------------------------------------------- */ -const char* CWifi::SSID(uint8_t networkItem) { // FIXME - // return CLwipIf::getInstance().getSSID(networkItem); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -int32_t CWifi::RSSI(uint8_t networkItem) { // FIXME - // return CLwipIf::getInstance().getRSSI(networkItem); -} -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -uint8_t CWifi::encryptionType(uint8_t networkItem) { // FIXME - // return CLwipIf::getInstance().getEncrType(networkItem); +const char* CWifi::SSID() { + return WiFiStation.getSSID(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { // FIXME - // return CLwipIf::getInstance().getBSSID(networkItem,bssid); +int32_t CWifi::RSSI() { + return WiFiStation.getRSSI(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -uint8_t CWifi::channel(uint8_t networkItem) { // FIXME - // return CLwipIf::getInstance().getChannel(networkItem); +uint8_t CWifi::encryptionType() { + return WiFiStation.getEncryptionType(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -const char* CWifi::SSID() { // FIXME -/* -------------------------------------------------------------------------- */ - // if(ni != nullptr) { - // return ni->getSSID(); - // } - // return ""; +uint8_t* CWifi::BSSID(uint8_t* bssid) { + return WiFiStation.getBSSID(bssid); } - /* -------------------------------------------------------------------------- */ -uint8_t* CWifi::BSSID(uint8_t* bssid) { // FIXME -/* -------------------------------------------------------------------------- */ - // if(ni != nullptr) { - // return ni->getBSSID(bssid); - // } - // return nullptr; -} /* -------------------------------------------------------------------------- */ -int32_t CWifi::RSSI() { // FIXME -/* -------------------------------------------------------------------------- */ - // if(ni != nullptr) { - // return ni->getRSSI(); - // } - // return 0; +uint8_t CWifi::channel() { + return WiFiStation.getChannel(); } - /* -------------------------------------------------------------------------- */ -uint8_t CWifi::encryptionType() { // FIXME -/* -------------------------------------------------------------------------- */ - // if(ni != nullptr) { - // return ni->getEncryptionType(); - // } - // return 0; -} /* -------------------------------------------------------------------------- */ uint8_t CWifi::status() { // FIXME @@ -278,21 +228,21 @@ uint8_t CWifi::status() { // FIXME } /* -------------------------------------------------------------------------- */ -int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { // FIXME +int CWifi::hostByName(const char* aHostname, IPAddress& aResult) { /* -------------------------------------------------------------------------- */ - // return CLwipIf::getInstance().getHostByName(aHostname,aResult); + return CLwipIf::getInstance().getHostByName(aHostname, aResult); } /* -------------------------------------------------------------------------- */ -void CWifi::lowPowerMode() { // FIXME +void CWifi::lowPowerMode() { /* -------------------------------------------------------------------------- */ - // CLwipIf::getInstance().setLowPowerMode(); + WiFiStation.setLowPowerMode(); } /* -------------------------------------------------------------------------- */ -void CWifi::noLowPowerMode() { // FIXME +void CWifi::noLowPowerMode() { /* -------------------------------------------------------------------------- */ - // CLwipIf::getInstance().resetLowPowerMode(); + WiFiStation.resetLowPowerMode(); } uint8_t CWifi::reasonCode() { diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 9192028e..27da6b80 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -184,47 +184,7 @@ class CWifi { */ int8_t scanNetworks(); - /* - * Return the SSID discovered during the network scan. - * - * param networkItem: specify from which network item want to get the information - * - * return: SSID string of the specified item on the networks scanned list - */ - const char* SSID(uint8_t networkItem); - - /* - * Return the encryption type of the networks discovered during the scanNetworks - * - * param networkItem: specify from which network item want to get the information - * - * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list - - * enum wl_enc_type : - * ENC_TYPE_WEP, - * ENC_TYPE_WPA, - * ENC_TYPE_WPA2, - * ENC_TYPE_WPA2_ENTERPRISE, - * ENC_TYPE_WPA3, - * ENC_TYPE_NONE, - * ENC_TYPE_AUTO, - * - * ENC_TYPE_UNKNOWN = 255 - * - */ - uint8_t encryptionType(uint8_t networkItem); - - uint8_t* BSSID(uint8_t networkItem, uint8_t* bssid); - uint8_t channel(uint8_t networkItem); - - /* - * Return the RSSI of the networks discovered during the scanNetworks - * - * param networkItem: specify from which network item want to get the information - * - * return: signed value of RSSI of the specified item on the networks scanned list - */ - int32_t RSSI(uint8_t networkItem); + uint8_t channel(); /* * Return Connection status. diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index f090f8e5..ab61d224 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -10,8 +10,11 @@ // TODO implement stop softAP and include it in the destructor of the class // TODO split netif definition in different files // TODO implement WIFINetworkDriver that is then being used by both Wifi station and softAP. This will allow to use both at the same time +// TODO adapt network statistics collection +// TODO define enum for error collection and return them instead of int value +// FIXME Wifi driver requires interrupt safety in order to work properly in the timer -extern "C" void dhcps_start(struct netif *netif); // TODO understand why not include +extern "C" void dhcps_start(struct netif *netif); err_t _netif_init(struct netif* ni); err_t _netif_output(struct netif* ni, struct pbuf* p); @@ -123,7 +126,7 @@ static void timer_cb(timer_callback_args_t* arg) { #endif void CLwipIf::task() { - for(CNetIf* iface: this->ifaces) { // FIXME is this affecting performances? + for(CNetIf* iface: this->ifaces) { iface->task(); } @@ -141,7 +144,7 @@ void CLwipIf::setDefaultIface(CNetIf* iface) { void CLwipIf::add_iface(CNetIf* iface) { // if it is the first interface set it as the default route if(this->ifaces.empty()) { - netif_set_default(&iface->ni); // TODO let the user decide which is the default one + netif_set_default(&iface->ni); #ifdef LWIP_USE_TIMER timer.setup_overflow_irq(); @@ -155,18 +158,8 @@ void CLwipIf::add_iface(CNetIf* iface) { } CLwipIf::~CLwipIf() { - // TODO free iface array } - -// int CLwipIf::setWifiMode(WifiMode_t mode) { - // TODO adapt this - // CLwipIf::getInstance().startSyncRequest(); - // int rv = CEspControl::getInstance().setWifiMode(mode); - // CLwipIf::getInstance().restartAsyncRequest(); - // return rv; -// } - /* *************************************************************************** * DNS related functions * ****************************************************************************/ @@ -182,6 +175,7 @@ static void _getHostByNameCBK(const char *name, const ip_addr_t *ipaddr, void *c cbk->cbk(toArduinoIP(ipaddr)); + delete ipaddr; delete cbk; } @@ -213,6 +207,12 @@ void CLwipIf::clearDnsServers() { } } +IPAddress CLwipIf::getDns(int n) { + ip_addr_t dns = dns_getserver(i); + + return toArduinoIP(dns); +} + // DNS resolution works with a callback if the resolution doesn't return immediately int CLwipIf::getHostByName(const char* aHostname, IPAddress& aResult, bool execute_task) { /* this has to be a blocking call but we need to understand how to handle wait time @@ -243,18 +243,18 @@ int CLwipIf::getHostByName(const char* aHostname, IPAddress& aResult, bool execu // TODO instead of returning int return an enum value int CLwipIf::getHostByName(const char* aHostname, std::function cbk) { - ip_addr_t addr; // TODO understand if this needs to be in the heap + ip_addr_t *addr = new ip_addr_t; uint8_t res = 0; dns_callback* dns_cbk = new dns_callback; dns_cbk->cbk = cbk; - err_t err = dns_gethostbyname(aHostname, &addr, _getHostByNameCBK, dns_cbk); + err_t err = dns_gethostbyname(aHostname, addr, _getHostByNameCBK, dns_cbk); switch(err) { case ERR_OK: // the address was already present in the local cache - cbk(toArduinoIP(&addr)); - + cbk(toArduinoIP(addr)); + delete ipaddr; delete dns_cbk; break; case ERR_INPROGRESS: @@ -263,6 +263,7 @@ int CLwipIf::getHostByName(const char* aHostname, std::functionstats); // TODO create a proper stats interface + // NETIF_STATS_INIT(this->stats); if(driver != nullptr) { - // driver->stats = this->stats; // TODO + // driver->stats = this->stats; // TODO check that this calls are effective driver->setLinkDownCallback(std::bind(&CNetIf::linkDownCallback, this)); driver->setLinkUpCallback(std::bind(&CNetIf::linkUpCallback, this)); @@ -311,11 +312,9 @@ int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) ethernet_input ); if(_ni == nullptr) { - // FIXME error if netif_add, return error return -1; } - //TODO add link up and down callback and set the link netif_set_up(&this->ni); #ifdef LWIP_DHCP @@ -334,7 +333,7 @@ int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) void CNetIf::task() { #ifdef LWIP_DHCP - // TODO we can add a lazy evaluated timer for this condition if dhcp_supplied_address takes too long + // TODO add timeout if(!this->dhcp_acquired && dhcp_supplied_address(&this->ni)) { dhcp_acquired = true; } @@ -375,11 +374,11 @@ void CNetIf::setLinkDown() { } void CNetIf::linkUpCallback() { - netif_set_link_up(&this->ni); // TODO check that this sets the interface up also + netif_set_link_up(&this->ni); } void CNetIf::linkDownCallback() { - netif_set_link_down(&this->ni); // TODO check that this sets the interface down also + netif_set_link_down(&this->ni); } /* ########################################################################## @@ -436,9 +435,9 @@ int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw, c // Call the begin function on the Parent class to init the interface CNetIf::begin(ip, nm, gw); - netif_set_link_up(&this->ni); // TODO test that moving this here still makes ethernet work + netif_set_link_up(&this->ni); - // TODO set dns server + CLwipIf::getInstance().addDnsServer(dns); return 0; } @@ -446,12 +445,11 @@ int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw, c err_t CEth::init(struct netif* ni) { // Setting up netif #if LWIP_NETIF_HOSTNAME - // TODO pass the hostname in the constructor os with a setter ni->hostname = "C33_eth"; #endif ni->name[0] = CEth::eth_ifname_prefix; ni->name[1] = '0' + CEth::eth_id++; - ni->mtu = 1500; // FIXME get this from the network + ni->mtu = 1500; // TODO get this from the network ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; memcpy(ni->hwaddr, this->driver->getMacAddress(), 6); // FIXME handle this using a constant @@ -529,15 +527,13 @@ uint8_t CWifiStation::wifistation_id = 0; CWifiStation::CWifiStation() : hw_init(false) { - // TODO this class should implement the driver interface - // CLwipIf::getInstance() } CWifiStation::~CWifiStation() { } -int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { // TODO This should be called only once, make it private +int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { int res = 0; int time_num = 0; @@ -565,7 +561,6 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres res = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); CNetIf::begin(ip, nm, gw); - // netif_set_link_up(&this->ni); // TODO this should be set only when successfully connected to an AP exit: // arduino::unlock(); return res; @@ -579,11 +574,7 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { // AccessPoint_t* best_matching_ap; // arduino::lock(); - // if(access_points.size() == 0) { - // this->scanForAp(); - // } if((rv=this->scanForAp()) != WL_SCAN_COMPLETED) { - // rv = -1; // FIXME set proper error code goto exit; } @@ -614,7 +605,7 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { memcpy(ap.bssid, access_points[best_index].bssid, BSSID_LENGTH); // arduino::lock(); - CEspControl::getInstance().communicateWithEsp(); // TODO make this shared between SoftAP and station + CEspControl::getInstance().communicateWithEsp(); rv=CEspControl::getInstance().connectAccessPoint(ap); // arduino::unlock(); @@ -626,9 +617,6 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { } // arduino::unlock(); } - // else { - // // TODO return AP not found error - // } exit: // arduino::unlock(); @@ -638,15 +626,14 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { int CWifiStation::scanForAp() { // arduino::lock(); - access_points.clear(); // FIXME create access_points vector + access_points.clear(); int res = CEspControl::getInstance().getAccessPointScanList(access_points); if (res == ESP_CONTROL_OK) { res = WL_SCAN_COMPLETED; + } else { + res = WL_NO_SSID_AVAIL; } - // else { - // res = WL_NO_SSID_AVAIL; // TODO - // } // arduino::unlock(); @@ -661,7 +648,6 @@ int CWifiStation::disconnectFromAp() { err_t CWifiStation::init(struct netif* ni) { // Setting up netif #if LWIP_NETIF_HOSTNAME - // TODO pass the hostname in the constructor os with a setter ni->hostname = "C33-WifiSta"; #endif ni->name[0] = CWifiStation::wifistation_ifname_prefix; @@ -734,9 +720,6 @@ void CWifiStation::task() { // calling the base class task, in order to make thigs work CNetIf::task(); - // TODO in order to make things easier this should be implemented inside of Wifi driver - // and not override LWIPInterface method - uint8_t if_num = 0; uint16_t dim = 0; uint8_t* buffer = nullptr; @@ -746,7 +729,7 @@ void CWifiStation::task() { // arduino::lock(); // TODO do not perform this when not connected to an AP if(hw_init) { - CEspControl::getInstance().communicateWithEsp(); // TODO make this shared between SoftAP and station + CEspControl::getInstance().communicateWithEsp(); // TODO handling buffer this way may be harmful for the memory buffer = CEspControl::getInstance().getStationRx(if_num, dim); @@ -755,7 +738,6 @@ void CWifiStation::task() { // empty the ESP32 queue while(buffer != nullptr) { // FIXME this section is redundant and should be generalized toghether with CEth::consume_callback - // TODO understand if this should be moved into the base class // NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS(this->stats); zerocopy_pbuf_t *custom_pbuf = get_zerocopy_pbuf(buffer, dim, free); @@ -795,7 +777,7 @@ uint8_t* CWifiStation::getBSSID(uint8_t* bssid){ } int32_t CWifiStation::getRSSI() { - // TODO should this be updated? + // TODO update the rssi on request of this method return (uint32_t)access_point_cfg.rssi; } @@ -806,9 +788,17 @@ uint8_t CWifiStation::getEncryptionType() { // int CWifiStation::getMacAddress(uint8_t* mac) { // } -// uint8_t CWifiStation::getChannel() { -// return (uint8_t)access_point_cfg.channel; -// } +uint8_t CWifiStation::getChannel() { + return (uint8_t)access_point_cfg.channel; +} + +int CWifiStation::setLowPowerMode() { + return CEspControl::getInstance().setPowerSaveMode(1); +} + +int CWifiStation::resetLowPowerMode() { + return CEspControl::getInstance().setPowerSaveMode(1); +} /* ########################################################################## */ /* CWifiSoftAp NETWORK INTERFACE CLASS */ @@ -851,7 +841,6 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress res = CEspControl::getInstance().setWifiMode(WIFI_MODE_AP); - // netif_set_link_up(&this->ni); // TODO this should be set only when successfully connected to an AP CNetIf::begin( default_dhcp_server_ip, default_nm, @@ -881,8 +870,7 @@ int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t c channel = (channel == 0) ? 1 : channel; cfg.channel = (channel > MAX_CHNL_NO) ? MAX_CHNL_NO : channel; - cfg.max_connections = 10; // FIXME - // cfg.max_connections = MAX_SOFAT_CONNECTION_DEF; // FIXME + cfg.max_connections = MAX_SOFAT_CONNECTION_DEF; // FIXME make user decide this parameter cfg.bandwidth = WIFI_BW_HT40; cfg.ssid_hidden = false; @@ -989,7 +977,7 @@ void CWifiSoftAp::task() { // arduino::lock(); // TODO do not perform this when not connected to an AP if(hw_init) { - CEspControl::getInstance().communicateWithEsp(); // TODO make this shared between SoftAP and station + CEspControl::getInstance().communicateWithEsp(); // TODO handling buffer this way may be harmful for the memory buffer = CEspControl::getInstance().getSoftApRx(if_num, dim); @@ -1037,6 +1025,18 @@ uint8_t CWifiSoftAp::getEncryptionType() { return Encr2wl_enc(soft_ap_cfg.encryption_mode); } +uint8_t CWifiSoftAp::getChannel() { + return (uint8_t)soft_ap_cfg.channel; +} + +int CWifiSoftAp::setLowPowerMode() { + return CEspControl::getInstance().setPowerSaveMode(1); +} + +int CWifiSoftAp::resetLowPowerMode() { + return CEspControl::getInstance().setPowerSaveMode(1); +} + /* ########################################################################## * DEBUG UTILS * ########################################################################## */ diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index fd2fbe5a..f412041d 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -205,12 +205,6 @@ class CEth : public CNetIf { const IPAddress &gw = INADDR_NONE, const IPAddress &dns = INADDR_NONE); - // virtual int begin( - // const IPAddress &ip = INADDR_NONE, - // const IPAddress &nm = INADDR_NONE, - // const IPAddress &gw = INADDR_NONE, - // const IPAddress &dns = INADDR_NONE); - virtual int getMacAddress(uint8_t* mac) override { UNUSED(mac); // FIXME not implemented return 1; @@ -254,12 +248,18 @@ class CWifiStation : public CNetIf { virtual void task() override; - virtual int getMacAddress(uint8_t* mac) override {} + virtual int getMacAddress(uint8_t* mac) override { + // FIXME not implemented + } virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); virtual int32_t getRSSI(); virtual uint8_t getEncryptionType(); + virtual uint8_t getChannel(); + + int setLowPowerMode(); + int resetLowPowerMode(); protected: static const char wifistation_ifname_prefix = 'w'; static uint8_t wifistation_id; @@ -293,11 +293,17 @@ class CWifiSoftAp : public CNetIf { int startSoftAp(const char* ssid, const char* passphrase=nullptr, uint8_t channel=0); int stopSoftAp(); - virtual int getMacAddress(uint8_t* mac) override {} + virtual int getMacAddress(uint8_t* mac) override { + // FIXME not implemented + } virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); virtual uint8_t getEncryptionType(); + virtual uint8_t getChannel(); + + int setLowPowerMode(); + int resetLowPowerMode(); protected: static const char softap_ifname_prefix = 's'; static uint8_t softap_id; @@ -349,6 +355,8 @@ class CLwipIf { uint8_t addDnsServer(const IPAddress& aDNSServer, int8_t priority=-1); void clearDnsServers(); + IPAddress getDns(int n); + // DNS resolution works with a callback if the resolution doesn't return immediately int getHostByName(const char* aHostname, IPAddress& aResult, bool execute_task=false); // blocking call int getHostByName(const char* aHostname, std::function cbk); // callback version From 719e63fb608e118522639b2dc1ae9777beec18cd Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 9 Jan 2024 16:43:00 +0100 Subject: [PATCH 41/79] fixing dns related functions --- libraries/lwIpWrapper/src/CNetIf.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index ab61d224..f7d1f162 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -208,7 +208,7 @@ void CLwipIf::clearDnsServers() { } IPAddress CLwipIf::getDns(int n) { - ip_addr_t dns = dns_getserver(i); + const ip_addr_t* dns = dns_getserver(n); return toArduinoIP(dns); } @@ -254,7 +254,7 @@ int CLwipIf::getHostByName(const char* aHostname, std::function Date: Thu, 14 Dec 2023 19:30:48 +0100 Subject: [PATCH 42/79] CNetIf - added config method to apply new static IP settings in CWifi::_config netif_set_address call was missing. in Ethernet::begin static IP was not applied if invoked second time now the new CNetIf.config does the static IP change for both. --- libraries/WiFi/src/WiFi.cpp | 28 ++++++++++++---------------- libraries/lwIpWrapper/src/CNetIf.cpp | 21 ++++++++++++++++++++- libraries/lwIpWrapper/src/CNetIf.h | 1 + 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 1be48463..2534795a 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -79,22 +79,18 @@ void CWifi::config(IPAddress local_ip) { // FIXME extern uint8_t *IpAddress2uint8(IPAddress a); /* -------------------------------------------------------------------------- */ -void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { // FIXME -/* -------------------------------------------------------------------------- */ - // _useStaticIp = local_ip != INADDR_NONE; - // if(ni != nullptr) { - // ni->DhcpStop(); - // ni->DhcpNotUsed(); - // IP_ADDR4(&ni->ip, local_ip[0], local_ip[1], local_ip[2], local_ip[3]); - // IP_ADDR4(&ni->gw, gateway[0], gateway[1], gateway[2], gateway[3]); - // IP_ADDR4(&ni->nm, subnet[0], subnet[1], subnet[2], subnet[3]); - // } - // else { - // CNetIf::default_ip = local_ip; - // CNetIf::default_nm = subnet; - // CNetIf::default_gw = gateway; - // CNetIf::default_dhcp_server_ip = local_ip; - // } +void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { +/* -------------------------------------------------------------------------- */ + _useStaticIp = local_ip != INADDR_NONE; + if(ni != nullptr) { + ni->config(local_ip, gateway, subnet); + } + else { + CNetIf::default_ip = local_ip; + CNetIf::default_nm = subnet; + CNetIf::default_gw = gateway; + CNetIf::default_dhcp_server_ip = local_ip; + } } /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index f7d1f162..c51a6793 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -948,7 +948,7 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { errval = ERR_OK; // NETIF_STATS_INCREMENT_TX_BYTES(this->stats, size); // NETIF_STATS_TX_TIME_AVERAGE(this->stats); - } else { + } else { // NETIF_STATS_INCREMENT_ERROR(this->stats, err); // NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS(this->stats); } @@ -961,6 +961,25 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { return errval; } +/* -------------------------------------------------------------------------- */ +void CNetIf::config(IPAddress _ip, IPAddress _gw, IPAddress _nm) +{ + DhcpStop(); + DhcpNotUsed(); + + IP_ADDR4(&ip, _ip[0], _ip[1], _ip[2], _ip[3]); + IP_ADDR4(&nm, _nm[0], _nm[1], _nm[2], _nm[3]); + IP_ADDR4(&gw, _gw[0], _gw[1], _gw[2], _gw[3]); + + netif_set_addr(&ni, &ip, &nm, &gw); + + if (netif_is_link_up(&ni)) { + netif_set_down(&ni); + netif_set_up(&ni); + } +} + + void CWifiSoftAp::task() { // calling the base class task, in order to make thigs work CNetIf::task(); diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index f412041d..faefa6bc 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -160,6 +160,7 @@ class CNetIf: public NetworkInterface { // memset(hostname, 0x00, MAX_HOSTNAME_DIM); // memcpy(hostname, name, strlen(name) < MAX_HOSTNAME_DIM ? strlen(name) : MAX_HOSTNAME_DIM); // } + void config(IPAddress _ip, IPAddress _gw, IPAddress _nm); virtual int getMacAddress(uint8_t* mac) = 0; From 45c85f35b8eaad61604a7e53b286f88de3c72dd6 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 9 Jan 2024 16:52:50 +0100 Subject: [PATCH 43/79] adapting cherry pick --- libraries/WiFi/src/WiFi.cpp | 13 ++----------- libraries/lwIpWrapper/src/CNetIf.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 2534795a..33650bd7 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -80,17 +80,8 @@ extern uint8_t *IpAddress2uint8(IPAddress a); /* -------------------------------------------------------------------------- */ void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { -/* -------------------------------------------------------------------------- */ - _useStaticIp = local_ip != INADDR_NONE; - if(ni != nullptr) { - ni->config(local_ip, gateway, subnet); - } - else { - CNetIf::default_ip = local_ip; - CNetIf::default_nm = subnet; - CNetIf::default_gw = gateway; - CNetIf::default_dhcp_server_ip = local_ip; - } +/* -------------------------------------------------------------------------- */ + CWifiStation.config(local_ip, gateway, subnet) } /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index c51a6793..c6900c9b 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -964,12 +964,12 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { /* -------------------------------------------------------------------------- */ void CNetIf::config(IPAddress _ip, IPAddress _gw, IPAddress _nm) { - DhcpStop(); - DhcpNotUsed(); + dhcpStop(); + dhcpStart(); - IP_ADDR4(&ip, _ip[0], _ip[1], _ip[2], _ip[3]); - IP_ADDR4(&nm, _nm[0], _nm[1], _nm[2], _nm[3]); - IP_ADDR4(&gw, _gw[0], _gw[1], _gw[2], _gw[3]); + ip_addr_t ip = fromArduinoIP(_ip); + ip_addr_t nm = fromArduinoIP(_gw); + ip_addr_t gw = fromArduinoIP(_nm); netif_set_addr(&ni, &ip, &nm, &gw); From 664fc698fc2d7041a5483effb56acd5e5bd68839 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 9 Jan 2024 16:56:04 +0100 Subject: [PATCH 44/79] moving funtion in correct section in file --- libraries/lwIpWrapper/src/CNetIf.cpp | 37 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index c6900c9b..180107df 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -385,6 +385,24 @@ void CNetIf::linkDownCallback() { * DHCP related functions * ########################################################################## */ +void CNetIf::config(IPAddress _ip, IPAddress _gw, IPAddress _nm) { +#ifdef LWIP_DHCP + dhcpStop(); + dhcpStart(); +#endif + + ip_addr_t ip = fromArduinoIP(_ip); + ip_addr_t nm = fromArduinoIP(_gw); + ip_addr_t gw = fromArduinoIP(_nm); + + netif_set_addr(&ni, &ip, &nm, &gw); + + if (netif_is_link_up(&ni)) { + netif_set_down(&ni); + netif_set_up(&ni); + } +} + #ifdef LWIP_DHCP @@ -961,25 +979,6 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { return errval; } -/* -------------------------------------------------------------------------- */ -void CNetIf::config(IPAddress _ip, IPAddress _gw, IPAddress _nm) -{ - dhcpStop(); - dhcpStart(); - - ip_addr_t ip = fromArduinoIP(_ip); - ip_addr_t nm = fromArduinoIP(_gw); - ip_addr_t gw = fromArduinoIP(_nm); - - netif_set_addr(&ni, &ip, &nm, &gw); - - if (netif_is_link_up(&ni)) { - netif_set_down(&ni); - netif_set_up(&ni); - } -} - - void CWifiSoftAp::task() { // calling the base class task, in order to make thigs work CNetIf::task(); From 3a1e29d1a54dd5ccf5aaaf56cd709e86ffc6f5ac Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 9 Jan 2024 16:56:22 +0100 Subject: [PATCH 45/79] added dhcp_inform call --- libraries/lwIpWrapper/src/CNetIf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 180107df..bb7603c7 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -389,6 +389,7 @@ void CNetIf::config(IPAddress _ip, IPAddress _gw, IPAddress _nm) { #ifdef LWIP_DHCP dhcpStop(); dhcpStart(); + dhcpNotUsed(); #endif ip_addr_t ip = fromArduinoIP(_ip); From b5eb21b5c804d19fd4b8cf30d21426461549dc36 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 01:47:18 +0100 Subject: [PATCH 46/79] fixing compilation issue --- libraries/WiFi/src/WiFi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 33650bd7..e39a27cb 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -81,7 +81,7 @@ extern uint8_t *IpAddress2uint8(IPAddress a); /* -------------------------------------------------------------------------- */ void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { /* -------------------------------------------------------------------------- */ - CWifiStation.config(local_ip, gateway, subnet) + WiFiStation.config(local_ip, gateway, subnet); } /* -------------------------------------------------------------------------- */ From ae01d585cb59e4a0981b0af4cdeb502cb4ae3432 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 01:47:38 +0100 Subject: [PATCH 47/79] removing FIXME --- libraries/WiFi/src/WiFi.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index e39a27cb..4a78fa27 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -67,13 +67,13 @@ uint8_t CWifi::beginAP(const char *ssid, const char* passphrase, uint8_t channel /* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip) { // FIXME +void CWifi::config(IPAddress local_ip) { /* -------------------------------------------------------------------------- */ - // IPAddress _nm(255, 255, 255, 0); - // IPAddress _gw = local_ip; - // _gw[3] = 1; + IPAddress _nm(255, 255, 255, 0); + IPAddress _gw = local_ip; + _gw[3] = 1; - // _config(local_ip, _gw, _nm); + _config(local_ip, _gw, _nm); } extern uint8_t *IpAddress2uint8(IPAddress a); @@ -85,10 +85,10 @@ void CWifi::_config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { } /* -------------------------------------------------------------------------- */ -void CWifi::config(IPAddress local_ip, IPAddress dns_server) { // FIXME +void CWifi::config(IPAddress local_ip, IPAddress dns_server) { /* -------------------------------------------------------------------------- */ config(local_ip); - // CLwipIf::getInstance().addDns(dns_server); + CLwipIf::getInstance().addDnsServer(dns_server, 0); } /* -------------------------------------------------------------------------- */ @@ -109,14 +109,14 @@ void CWifi::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1) { /* -------------------------------------------------------------------------- */ - // CLwipIf::getInstance().addDns(dns_server1); + CLwipIf::getInstance().addDnsServer(dns_server1, 0); } /* -------------------------------------------------------------------------- */ void CWifi::setDNS(IPAddress dns_server1, IPAddress dns_server2) { /* -------------------------------------------------------------------------- */ - // CLwipIf::getInstance().addDns(dns_server1); - // CLwipIf::getInstance().addDns(dns_server2); + CLwipIf::getInstance().addDnsServer(dns_server1, 0); + CLwipIf::getInstance().addDnsServer(dns_server2, 1); } /* -------------------------------------------------------------------------- */ From f8507fab6f089fa364ff7ef02c05422dcddaf301 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 03:09:06 +0100 Subject: [PATCH 48/79] restoring CWiFi methods to extract scanned access point info --- libraries/WiFi/src/WiFi.cpp | 30 ++++++++++++++++++ libraries/WiFi/src/WiFiC3.h | 47 +++++++++++++++++++++++++--- libraries/lwIpWrapper/src/CNetIf.cpp | 37 ++++++++++++++++++++++ libraries/lwIpWrapper/src/CNetIf.h | 6 ++++ 4 files changed, 116 insertions(+), 4 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index 4a78fa27..bfe4906d 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -208,6 +208,36 @@ uint8_t CWifi::channel() { } /* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +const char* CWifi::SSID(uint8_t networkItem) { + return WiFiStation.getSSID(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +int32_t CWifi::RSSI(uint8_t networkItem) { + return WiFiStation.getRSSI(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::encryptionType(uint8_t networkItem) { + return WiFiStation.getEncrType(networkItem); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +uint8_t* CWifi::BSSID(uint8_t networkItem, uint8_t* bssid) { + return WiFiStation.getBSSID(networkItem,bssid); +} +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +uint8_t CWifi::channel(uint8_t networkItem) { + return WiFiStation.getChannel(networkItem); +} +/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ uint8_t CWifi::status() { // FIXME /* -------------------------------------------------------------------------- */ diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 27da6b80..ae5112f9 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -171,10 +171,10 @@ class CWifi { int32_t RSSI(); /* - * Return the Encryption Type associated with the network - * - * return: one value of wl_enc_type enum - */ + * Return the Encryption Type associated with the network + * + * return: one value of wl_enc_type enum + */ uint8_t encryptionType(); /* @@ -183,6 +183,45 @@ class CWifi { * return: Number of discovered networks */ int8_t scanNetworks(); + /* + * Return the SSID discovered during the network scan. + * + * param networkItem: specify from which network item want to get the information + * + * return: SSID string of the specified item on the networks scanned list + */ + const char* SSID(uint8_t networkItem); + + /* + * Return the encryption type of the networks discovered during the scanNetworks + * + * param networkItem: specify from which network item want to get the information + * + * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list + * enum wl_enc_type : + * ENC_TYPE_WEP, + * ENC_TYPE_WPA, + * ENC_TYPE_WPA2, + * ENC_TYPE_WPA2_ENTERPRISE, + * ENC_TYPE_WPA3, + * ENC_TYPE_NONE, + * ENC_TYPE_AUTO, + * ENC_TYPE_UNKNOWN = 255 + */ + uint8_t encryptionType(uint8_t networkItem); + + uint8_t* BSSID(uint8_t networkItem, uint8_t* bssid); + uint8_t channel(uint8_t networkItem); + + /* + * Return the RSSI of the networks discovered during the scanNetworks + * + * param networkItem: specify from which network item want to get the information + * + * return: signed value of RSSI of the specified item on the networks scanned list + */ + int32_t RSSI(uint8_t networkItem); + uint8_t channel(); diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index bb7603c7..fd38b279 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -811,6 +811,43 @@ uint8_t CWifiStation::getChannel() { return (uint8_t)access_point_cfg.channel; } +const char* CWifiStation::getSSID(uint8_t i) +{ + if (access_points.size() > 0 && i < access_points.size()) { + return (const char*)access_points[i].ssid; + } + return nullptr; +} + +int32_t CWifiStation::getRSSI(uint8_t i) { + if (access_points.size() > 0 && i < access_points.size()) { + return (int32_t)access_points[i].rssi; + } + return 0; +} + +uint8_t CWifiStation::getEncrType(uint8_t i) { + if (access_points.size() > 0 && i < access_points.size()) { + return Encr2wl_enc(access_points[i].encryption_mode); + } + return 0; +} + +uint8_t* CWifiStation::getBSSID(uint8_t i, uint8_t* bssid) { + if (access_points.size() > 0 && i < access_points.size()) { + CNetUtilities::macStr2macArray(bssid, (const char*)access_points[i].bssid); + return bssid; + } + return nullptr; +} + +uint8_t CWifiStation::getChannel(uint8_t i) { + if (access_points.size() > 0 && i < access_points.size()) { + return (uint8_t)access_points[i].channel; + } + return 0; +} + int CWifiStation::setLowPowerMode() { return CEspControl::getInstance().setPowerSaveMode(1); } diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index faefa6bc..c49c73ef 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -259,6 +259,12 @@ class CWifiStation : public CNetIf { virtual uint8_t getEncryptionType(); virtual uint8_t getChannel(); + const char* getSSID(uint8_t i); + int32_t getRSSI(uint8_t i); + uint8_t getEncrType(uint8_t i); + uint8_t* getBSSID(uint8_t i, uint8_t* bssid); + uint8_t getChannel(uint8_t i); + int setLowPowerMode(); int resetLowPowerMode(); protected: From e0ce22c258e21d7e9373b42e40d3527bc74417a8 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 04:42:09 +0100 Subject: [PATCH 49/79] removing lwipMem files --- libraries/lwIpWrapper/src/lwipMem.cpp | 119 -------------------------- libraries/lwIpWrapper/src/lwipMem.h | 10 --- 2 files changed, 129 deletions(-) delete mode 100644 libraries/lwIpWrapper/src/lwipMem.cpp delete mode 100644 libraries/lwIpWrapper/src/lwipMem.h diff --git a/libraries/lwIpWrapper/src/lwipMem.cpp b/libraries/lwIpWrapper/src/lwipMem.cpp deleted file mode 100644 index bf255e63..00000000 --- a/libraries/lwIpWrapper/src/lwipMem.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "lwipMem.h" - -/* -------------------------------------------------------------------------- */ -/* MEMORY ALLOCATION FUNCTIONS */ -/* -------------------------------------------------------------------------- */ -/** - * @brief Allocate a pbuf with data pass in parameter - * @param p: pointer to pbuf - * @param buffer: pointer to data to store - * @param size: number of data to store - * @retval pointer to the pbuf allocated - */ -struct pbuf* pbuffer_put_data(struct pbuf* p, const uint8_t* buffer, size_t size) -{ - // Allocate memory if pbuf doesn't exit yet. - if (p == NULL) { - p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - - if (p != NULL) { - // Copy data inside pbuf - if (ERR_OK == pbuf_take(p, (uint8_t*)buffer, size)) { - return p; - } else { - pbuf_free(p); - } - } - } - // If pbuf allocated, grow the size of pbuf and add new data - // NOTE: pbuf_realloc can't be used to grow the size of pbuf - else { - struct pbuf* q = pbuf_alloc(PBUF_TRANSPORT, size + p->tot_len, PBUF_RAM); - - if (q != NULL) { - if (ERR_OK == pbuf_copy(q, p)) { - if (ERR_OK == pbuf_take_at(q, (uint8_t*)buffer, size, p->tot_len)) { - pbuf_free(p); - p = q; - return p; - } - } - - pbuf_free(q); - } - } - - return 0; -} - -/** - * @brief Free pbuf - * - * @param p: pointer to pbuf - * @retval return always NULL - */ -struct pbuf* pbuffer_free_data(struct pbuf* p) -{ - uint16_t n; - - if (p != NULL) { - do { - n = pbuf_free(p); - } while (n == 0); - } - - return NULL; -} - -/** - * @brief This function passes pbuf data to uin8_t buffer. It takes account if - * pbuf is chained. - * @param data pointer to data structure - * @param buffer the buffer where write the data read - * @param size the number of data to read - * @retval number of data read - */ -uint16_t pbuffer_get_data(struct pbuf_data* data, uint8_t* buffer, size_t size) -{ - uint16_t i; - uint16_t offset; - uint16_t nb; - struct pbuf* ptr; - - if ((data->p == NULL) || (buffer == NULL) || (size == 0) || (data->available == 0) || (data->available > data->p->tot_len)) { - return 0; - } - - nb = 0; - - while ((nb < size) && (data->p != NULL) && (data->available > 0)) { - ptr = data->p; - offset = ptr->tot_len - data->available; - - /* Get data from p */ - for (i = 0; (nb < size) && ((offset + i) < ptr->len) && (data->available > 0); i++) { - buffer[nb] = pbuf_get_at(ptr, offset + i); - nb++; - data->available--; - } - - if (nb < size) { - /* continue with next pbuf in chain (if any) */ - data->p = ptr->next; - - if (data->p != NULL) { - /* increment reference count for p */ - pbuf_ref(data->p); - } - - /* chop first pbuf from chain */ - ptr = pbuffer_free_data(ptr); - } - } - - if (data->available == 0) { - data->p = pbuffer_free_data(data->p); - } - - return nb; -} \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipMem.h b/libraries/lwIpWrapper/src/lwipMem.h deleted file mode 100644 index 8dc8be64..00000000 --- a/libraries/lwIpWrapper/src/lwipMem.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ARDUINO_LWIP_MEM_H -#define _ARDUINO_LWIP_MEM_H - -#include "lwipTypes.h" - -struct pbuf* pbuffer_put_data(struct pbuf* p, const uint8_t* buffer, size_t size); -struct pbuf* pbuffer_free_data(struct pbuf* p); -uint16_t pbuffer_get_data(struct pbuf_data* data, uint8_t* buffer, size_t size); - -#endif \ No newline at end of file From 4a1e9d4d2e637cfe114e23600c43b5beea4b697b Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 04:43:31 +0100 Subject: [PATCH 50/79] moving free_pbuf_chain to an external file in order to be shared from udp and tcp --- libraries/lwIpWrapper/src/lwipClient.cpp | 52 ++++-------------------- libraries/lwIpWrapper/src/lwipClient.h | 1 - libraries/lwIpWrapper/src/lwippbuf.cpp | 44 ++++++++++++++++++++ libraries/lwIpWrapper/src/lwippbuf.h | 12 ++++++ 4 files changed, 64 insertions(+), 45 deletions(-) create mode 100644 libraries/lwIpWrapper/src/lwippbuf.cpp create mode 100644 libraries/lwIpWrapper/src/lwippbuf.h diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 99821430..8dfc454c 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -5,6 +5,7 @@ extern "C" { #include "Arduino.h" #include "lwipClient.h" +#include "lwippbuf.h" #include "CNetIf.h" #include "utils.h" // FIXME understand hos to syncronize the interrupt thread and "userspace" @@ -310,8 +311,10 @@ int lwipClient::read(uint8_t* buffer, size_t size) { arduino::lock(); uint16_t copied = pbuf_copy_partial(this->tcp_info->pbuf_head, buffer, size, this->tcp_info->pbuf_offset); - this->free_pbuf_chain(copied); - // __enable_irq(); + this->tcp_info->pbuf_head = free_pbuf_chain(this->tcp_info->pbuf_head, copied, &this->tcp_info->pbuf_offset); + + // acknowledge the received data + tcp_recved(this->tcp_info->pcb, copied); arduino::unlock(); return copied; @@ -433,50 +436,11 @@ size_t lwipClient::read_until_token( uint16_t copied = pbuf_copy_partial(this->tcp_info->pbuf_head, (uint8_t*)buffer, buf_copy_len, this->tcp_info->pbuf_offset); - this->free_pbuf_chain(copied); - arduino::unlock(); - - return copied; -} - -void lwipClient::free_pbuf_chain(uint16_t copied) { - arduino::lock(); - /* - * free pbufs that have been copied, if copied == 0 we have an error - * free the buffer chain starting from the head up to the last entire pbuf ingested - * taking into account the previously not entirely consumed pbuf - */ - uint32_t tobefreed = 0; - copied += this->tcp_info->pbuf_offset; - - // in order to clean up the chain we need to find the pbuf in the last pbuf in the chain - // that got completely consumed by the application, dechain it from it successor and delete the chain before it - - struct pbuf *head = this->tcp_info->pbuf_head, *last=head, *prev=nullptr; // FIXME little optimization prev can be substituted by last->next - - while(last!=nullptr && last->len + tobefreed <= copied) { - tobefreed += last->len; - prev = last; - last = last->next; - } - - // dechain if we are not at the end of the chain (last == nullptr) - // and if we haven't copied entirely the first pbuf (prev == nullptr) (head == last) - // if we reached the end of the chain set the this pbuf pointer to nullptr - if(prev != nullptr) { - prev->next = nullptr; - this->tcp_info->pbuf_head = last; - } - - // the chain that is referenced by head is detached by the one referenced by this->tcp_info->pbuf_head - // free the chain if we haven't copied entirely the first pbuf (prev == nullptr) - if(this->tcp_info->pbuf_head != head) { - uint8_t refs = pbuf_free(head); - } - - this->tcp_info->pbuf_offset = copied - tobefreed; // This offset should be referenced to the first pbuf in queue + this->tcp_info->pbuf_head = free_pbuf_chain(this->tcp_info->pbuf_head, copied, &this->tcp_info->pbuf_offset); // acknowledge the received data tcp_recved(this->tcp_info->pcb, copied); arduino::unlock(); + + return copied; } diff --git a/libraries/lwIpWrapper/src/lwipClient.h b/libraries/lwIpWrapper/src/lwipClient.h index 17e9985d..446c4288 100644 --- a/libraries/lwIpWrapper/src/lwipClient.h +++ b/libraries/lwIpWrapper/src/lwipClient.h @@ -104,7 +104,6 @@ class lwipClient : public arduino::Client { ip_addr_t _ip; err_t connected_callback(struct tcp_pcb* tpcb, err_t err); - void free_pbuf_chain(uint16_t copied); err_t recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err); friend err_t _lwip_tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err); diff --git a/libraries/lwIpWrapper/src/lwippbuf.cpp b/libraries/lwIpWrapper/src/lwippbuf.cpp new file mode 100644 index 00000000..24c6c71d --- /dev/null +++ b/libraries/lwIpWrapper/src/lwippbuf.cpp @@ -0,0 +1,44 @@ +#include "lwippbuf.h" +#include "utils.h" + +struct pbuf* free_pbuf_chain(struct pbuf* p, uint16_t copied, uint16_t *offset) { + arduino::lock(); + /* + * free pbufs that have been copied, if copied == 0 we have an error + * free the buffer chain starting from the head up to the last entire pbuf ingested + * taking into account the previously not entirely consumed pbuf + */ + uint32_t tobefreed = 0; + copied += *offset; + + // in order to clean up the chain we need to find the pbuf in the last pbuf in the chain + // that got completely consumed by the application, dechain it from it successor and delete the chain before it + + struct pbuf *head = p, *last=head, *prev=nullptr; // FIXME little optimization prev can be substituted by last->next + + while(last!=nullptr && last->len + tobefreed <= copied) { + tobefreed += last->len; + prev = last; + last = last->next; + } + + // dechain if we are not at the end of the chain (last == nullptr) + // and if we haven't copied entirely the first pbuf (prev == nullptr) (head == last) + // if we reached the end of the chain set the this pbuf pointer to nullptr + if(prev != nullptr) { + prev->next = nullptr; + p = last; + } + + // the chain that is referenced by head is detached by the one referenced by p + // free the chain if we haven't copied entirely the first pbuf (prev == nullptr) + if(p != head) { + uint8_t refs = pbuf_free(head); + } + + *offset = copied - tobefreed; // This offset should be referenced to the first pbuf in queue + + arduino::unlock(); + + return p; +} \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwippbuf.h b/libraries/lwIpWrapper/src/lwippbuf.h new file mode 100644 index 00000000..498d6f9a --- /dev/null +++ b/libraries/lwIpWrapper/src/lwippbuf.h @@ -0,0 +1,12 @@ +#pragma once +#include + +/** + * This function aim to free a pbuf chain that has been partially consumed. + * @param p the head of the pbuf chain + * @param copied the size that had been consumed in the last operation + * @param offset the size that had been consumed in the previous operations, + * this value will be updated with the ffset of the new head + * @return the new pbuf head + */ +struct pbuf* free_pbuf_chain(struct pbuf* p, uint16_t copied, uint16_t *offset); \ No newline at end of file From 4980778fcd65385219235de0424c2c68d726558e Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 04:44:16 +0100 Subject: [PATCH 51/79] moving lwipTypes udp_struct into udp file --- libraries/lwIpWrapper/src/lwipTypes.h | 24 ------------------------ libraries/lwIpWrapper/src/lwipUDP.h | 12 ++++++++++-- 2 files changed, 10 insertions(+), 26 deletions(-) delete mode 100644 libraries/lwIpWrapper/src/lwipTypes.h diff --git a/libraries/lwIpWrapper/src/lwipTypes.h b/libraries/lwIpWrapper/src/lwipTypes.h deleted file mode 100644 index a0282de4..00000000 --- a/libraries/lwIpWrapper/src/lwipTypes.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef ARDUINO_LWIP_IF_TYPES_H -#define ARDUINO_LWIP_IF_TYPES_H - -#include "lwip/include/lwip/ip_addr.h" -#include "lwip/include/lwip/pbuf.h" -#include - -/* Exported types ------------------------------------------------------------*/ -/* Struct to store received data */ -struct pbuf_data { - struct pbuf* p; // the packet buffer that was received - uint16_t available; // number of data -}; - -/* UDP structure */ -struct udp_struct { - struct udp_pcb* pcb; /* pointer on the current udp_pcb */ - struct pbuf_data data; - ip_addr_t ip; // the remote IP address from which the packet was received - u16_t port; // the remote port from which the packet was received - std::function onDataArrival; -}; - -#endif diff --git a/libraries/lwIpWrapper/src/lwipUDP.h b/libraries/lwIpWrapper/src/lwipUDP.h index 2b0ee8c1..a023e9a6 100644 --- a/libraries/lwIpWrapper/src/lwipUDP.h +++ b/libraries/lwIpWrapper/src/lwipUDP.h @@ -5,11 +5,19 @@ #include #include "CNetIf.h" -#include "lwipMem.h" -#include "lwipTypes.h" #define UDP_TX_PACKET_MAX_SIZE 24 +/* UDP structure */ +struct udp_struct { + struct udp_pcb* pcb; /* pointer on the current udp_pcb */ + struct pbuf* p; + uint16_t pbuf_offset; + ip_addr_t ip; // the remote IP address from which the packet was received + u16_t port; // the remote port from which the packet was received + std::function onDataArrival; +}; + class lwipUDP : public UDP { private: uint16_t _port; // local port to listen on From 56c1d076e95f16c508b5e321550ba828f91bfc2c Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 10 Jan 2024 04:44:52 +0100 Subject: [PATCH 52/79] readapting udp class --- libraries/lwIpWrapper/src/lwipUDP.cpp | 95 +++++++++++++++------------ 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipUDP.cpp b/libraries/lwIpWrapper/src/lwipUDP.cpp index 2e84ac26..5385236c 100644 --- a/libraries/lwIpWrapper/src/lwipUDP.cpp +++ b/libraries/lwIpWrapper/src/lwipUDP.cpp @@ -5,6 +5,8 @@ #include "lwip/include/lwip/igmp.h" #include "lwip/include/lwip/ip_addr.h" +#include "utils.h" +#include "lwippbuf.h" #if LWIP_UDP /** @@ -25,12 +27,13 @@ void udp_receive_callback(void* arg, struct udp_pcb* pcb, struct pbuf* p, /* Send data to the application layer */ if ((udp_arg != NULL) && (udp_arg->pcb == pcb)) { // Free the old p buffer if not read - if (udp_arg->data.p != NULL) { - pbuf_free(udp_arg->data.p); + if (udp_arg->p != NULL) { + pbuf_free(udp_arg->p); + udp_arg->p = NULL; } - udp_arg->data.p = p; - udp_arg->data.available = p->len; + udp_arg->p = p; + udp_arg->pbuf_offset = 0; ip_addr_copy(udp_arg->ip, *addr); udp_arg->port = port; @@ -64,7 +67,8 @@ uint8_t lwipUDP::begin(IPAddress ip, uint16_t port, bool multicast) ip_addr_t ipaddr; err_t err; - // u8_to_ip_addr(rawIPAddress(ip), &ipaddr); // FIXME + ipaddr = fromArduinoIP(ip); + if (multicast) { err = udp_bind(_udp.pcb, IP_ADDR_ANY, port); } else { @@ -86,7 +90,7 @@ uint8_t lwipUDP::begin(IPAddress ip, uint16_t port, bool multicast) _port = port; _remaining = 0; - // CLwipIf::getInstance().lwip_task(); + CLwipIf::getInstance().task(); return 1; } @@ -107,7 +111,7 @@ void lwipUDP::stop() _udp.pcb = NULL; } - // CLwipIf::getInstance().lwip_task(); + CLwipIf::getInstance().task(); } int lwipUDP::beginPacket(const char* host, uint16_t port) @@ -135,7 +139,7 @@ int lwipUDP::beginPacket(IPAddress ip, uint16_t port) _sendtoPort = port; udp_recv(_udp.pcb, &udp_receive_callback, &_udp); - // CLwipIf::getInstance().lwip_task(); + CLwipIf::getInstance().task(); return 1; } @@ -145,18 +149,24 @@ int lwipUDP::endPacket() if ((_udp.pcb == NULL) || (_data == NULL)) { return 0; } - - ip_addr_t ipaddr; - // if (ERR_OK != udp_sendto(_udp.pcb, _data, u8_to_ip_addr(rawIPAddress(_sendtoIP), &ipaddr), _sendtoPort)) { - // __disable_irq(); - // _data = pbuffer_free_data(_data); - // __enable_irq(); - // return 0; - // } + /* + * FIXME in this way, the derived classes for wifi and ethernet won't send data through the correct iface + * the solution to this issue is by using udp_sendto_if, by this needs further rework + */ + ip_addr_t ipaddr = fromArduinoIP(_sendtoIP); + if (ERR_OK != udp_sendto( + _udp.pcb, _data, + &ipaddr, + _sendtoPort)) { + __disable_irq(); + pbuf_free(_data); + __enable_irq(); + return 0; + } _data = NULL; - // CLwipIf::getInstance().lwip_task(); + CLwipIf::getInstance().task(); return 1; } @@ -169,11 +179,20 @@ size_t lwipUDP::write(uint8_t byte) size_t lwipUDP::write(const uint8_t* buffer, size_t size) { __disable_irq(); - _data = pbuffer_put_data(_data, buffer, size); - __enable_irq(); - if (_data == NULL) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + + if(p == NULL) { return 0; } + pbuf_take(p, buffer, size); + + if(_data == NULL) { + _data = p; + } else { + // no need to increment the reference count of the pbuf, since it is already 1 + pbuf_cat(_data, p); + } + __enable_irq(); return size; } @@ -188,12 +207,12 @@ int lwipUDP::parsePacket() // read(); // } - // CLwipIf::getInstance().lwip_task(); + CLwipIf::getInstance().task(); - if (_udp.data.available > 0) { - // _remoteIP = IPAddress(ip_addr_to_u32(&(_udp.ip))); // FIXME + if (_udp.p == nullptr? 0: _udp.p->tot_len) { + _remoteIP = toArduinoIP(&_udp.ip); _remotePort = _udp.port; - _remaining = _udp.data.available; + _remaining = _udp.p->tot_len; return _remaining; } @@ -205,7 +224,7 @@ int lwipUDP::read() { uint8_t byte; - if (_udp.data.p == NULL) { + if (_udp.p == NULL) { return -1; } @@ -221,25 +240,19 @@ int lwipUDP::read() int lwipUDP::read(unsigned char* buffer, size_t len) { - if (_udp.data.p == NULL) { + if (_udp.p == NULL) { return -1; } if (_remaining > 0) { - int got; - - if (_remaining <= len) { - // data should fit in the buffer - __disable_irq(); - got = (int)pbuffer_get_data(&(_udp.data), (uint8_t*)buffer, _remaining); - __enable_irq(); - } else { - // too much data for the buffer, - // grab as much as will fit - __disable_irq(); - got = (int)pbuffer_get_data(&(_udp.data), (uint8_t*)buffer, len); - __enable_irq(); - } + __disable_irq(); + int got = pbuf_copy_partial( + _udp.p, + buffer, + _remaining < len ? _remaining : len, _udp.pbuf_offset); + + _udp.p = free_pbuf_chain(_udp.p, got, &_udp.pbuf_offset); + __enable_irq(); if (got > 0) { _remaining -= got; @@ -260,7 +273,7 @@ int lwipUDP::peek() if (!_remaining) { return -1; } - b = pbuf_get_at(_udp.data.p, 0); + b = pbuf_get_at(_udp.p, 0); return b; } From e1af45e2c7fec80d226e06e7283b0fd070a43f59 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 12 Jan 2024 10:36:10 +0100 Subject: [PATCH 53/79] improving task syncrhonization between timer and main context --- libraries/lwIpWrapper/src/CNetIf.cpp | 69 +++++++++++++--------------- libraries/lwIpWrapper/src/CNetIf.h | 19 +++++++- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index fd38b279..16791b03 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -25,7 +25,7 @@ static void _getHostByNameCBK(const char *name, const ip_addr_t *ipaddr, void *c #ifdef LWIP_USE_TIMER static void timer_cb(timer_callback_args_t* arg); -#endif +#endif // LWIP_USE_TIMER // Custom Pbuf definition used to handle RX zero copy // TODO Move this in a separate file (understand if it is required) @@ -40,7 +40,6 @@ static void zerocopy_pbuf_mem_free(struct pbuf *p) { // SYS_ARCH_DECL_PROTECT(zerocopy_pbuf_free); zerocopy_pbuf_t* zcpbuf = (zerocopy_pbuf_t*) p; - // arduino::lock(); // SYS_ARCH_PROTECT(zerocopy_pbuf_free); // FIXME pbufs may be allocated in a different memory pool, deallocate them accordingly @@ -48,8 +47,6 @@ static void zerocopy_pbuf_mem_free(struct pbuf *p) { zcpbuf->buffer = nullptr; mem_free(zcpbuf); // TODO understand if pbuf_free deletes the pbuf // SYS_ARCH_UNPROTECT(zerocopy_pbuf_free); - - // arduino::unlock(); } static inline zerocopy_pbuf_t* get_zerocopy_pbuf(uint8_t *buffer, uint32_t size, void(*buffer_free)(void*) = mem_free) { @@ -512,7 +509,6 @@ err_t CEth::output(struct netif* ni, struct pbuf* p) { void CEth::consume_callback(uint8_t* buffer, uint32_t len) { // TODO understand if this callback can be moved into the base class - // arduino::lock(); const uint16_t trimmed_size = len; @@ -536,7 +532,6 @@ void CEth::consume_callback(uint8_t* buffer, uint32_t len) { } else { // NETIF_STATS_INCREMENT_RX_BYTES(this->stats, p->len); } - // arduino::unlock(); } /* ########################################################################## */ @@ -556,7 +551,6 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres int res = 0; int time_num = 0; - // arduino::lock(); CEspControl::getInstance().listenForStationDisconnectEvent([this] (CCtrlMsgWrapper *resp) -> int { netif_set_link_down(&this->ni); return ESP_CONTROL_OK; @@ -578,10 +572,12 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres time_num++; } + CLwipIf::getInstance().sync_timer(); res = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); + CLwipIf::getInstance().enable_timer(); + CNetIf::begin(ip, nm, gw); exit: - // arduino::unlock(); return res; } @@ -590,8 +586,6 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { int rv = ESP_CONTROL_CTRL_ERROR; // FIXME this should be set with an error meaning AP not found bool found = false; int8_t best_index = -1; // this index is used to find the ap with the best rssi - // AccessPoint_t* best_matching_ap; - // arduino::lock(); if((rv=this->scanForAp()) != WL_SCAN_COMPLETED) { goto exit; @@ -606,62 +600,60 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { } } if(best_index != -1) { - // memset(ap.ssid, 0x00, SSID_LENGTH); // I shouldn't need to zero the ssid string pointer strncpy((char*)ap.ssid, ssid, SSID_LENGTH); - // memcpy(ap.ssid, access_points[best_index].ssid, SSID_LENGTH); - // memset(ap.pwd, 0x00, PASSWORD_LENGTH); if(passphrase != nullptr) { auto slen = strlen(passphrase)+1; strncpy((char*)ap.pwd, passphrase, (slen < PASSWORD_LENGTH) ? slen : PASSWORD_LENGTH); - // memcpy(ap.pwd, passphrase, (slen < PASSWORD_LENGTH) ? slen : PASSWORD_LENGTH); } else { - // memset(ap.pwd, 0x00, PASSWORD_LENGTH); ap.pwd[0] = '\0'; } memset(ap.bssid, 0x00, BSSID_LENGTH); memcpy(ap.bssid, access_points[best_index].bssid, BSSID_LENGTH); - // arduino::lock(); - CEspControl::getInstance().communicateWithEsp(); - + CLwipIf::getInstance().sync_timer(); rv=CEspControl::getInstance().connectAccessPoint(ap); - // arduino::unlock(); if (rv == ESP_CONTROL_OK) { CEspControl::getInstance().getAccessPointConfig(access_point_cfg); netif_set_link_up(&this->ni); } - // arduino::unlock(); + CLwipIf::getInstance().enable_timer(); } exit: - // arduino::unlock(); - return rv; } int CWifiStation::scanForAp() { - // arduino::lock(); access_points.clear(); + CLwipIf::getInstance().sync_timer(); + int res = CEspControl::getInstance().getAccessPointScanList(access_points); + CLwipIf::getInstance().enable_timer(); + if (res == ESP_CONTROL_OK) { res = WL_SCAN_COMPLETED; } else { res = WL_NO_SSID_AVAIL; } - // arduino::unlock(); return res; } // disconnect int CWifiStation::disconnectFromAp() { - return CEspControl::getInstance().disconnectAccessPoint(); + CLwipIf::getInstance().sync_timer(); + + auto res = CEspControl::getInstance().disconnectAccessPoint(); + + CLwipIf::getInstance().enable_timer(); + + return res; } err_t CWifiStation::init(struct netif* ni) { @@ -698,7 +690,6 @@ err_t CWifiStation::output(struct netif* _ni, struct pbuf* p) { // NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); // NETIF_STATS_TX_TIME_START(this->stats); - // arduino::lock(); // p may be a chain of pbufs if(p->next != nullptr) { buf = (uint8_t*) malloc(size*sizeof(uint8_t)); @@ -731,7 +722,6 @@ err_t CWifiStation::output(struct netif* _ni, struct pbuf* p) { if(p->next != nullptr && buf != nullptr) { free(buf); } - // arduino::unlock(); return errval; } @@ -745,7 +735,6 @@ void CWifiStation::task() { struct pbuf* p = nullptr; // NETIF_STATS_RX_TIME_START(this->stats); - // arduino::lock(); // TODO do not perform this when not connected to an AP if(hw_init) { CEspControl::getInstance().communicateWithEsp(); @@ -779,7 +768,6 @@ void CWifiStation::task() { buffer = CEspControl::getInstance().getStationRx(if_num, dim); } // NETIF_STATS_RX_TIME_AVERAGE(this->stats); - // arduino::unlock(); } // void CWifiStation::consume_callback(uint8_t* buffer, uint32_t len) { @@ -877,7 +865,6 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress int res = 0; int time_num = 0; - // arduino::lock(); CEspControl::getInstance().listenForInitEvent([this] (CCtrlMsgWrapper *resp) -> int { // Serial.println("init"); this->hw_init = true; @@ -895,7 +882,9 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress time_num++; } + CLwipIf::getInstance().sync_timer(); res = CEspControl::getInstance().setWifiMode(WIFI_MODE_AP); + CLwipIf::getInstance().enable_timer(); CNetIf::begin( default_dhcp_server_ip, @@ -903,13 +892,13 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress default_dhcp_server_ip ); exit: - // arduino::unlock(); return res; } // TODO scan the other access point first and then set the channel if 0 // TODO there are requirements for ssid and password int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t channel) { + CLwipIf::getInstance().sync_timer(); SoftApCfg_t cfg; strncpy((char*)cfg.ssid, ssid, SSID_LENGTH); @@ -942,7 +931,7 @@ int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t c // wifi_status = WL_AP_FAILED; } - + CLwipIf::getInstance().enable_timer(); return rv; } @@ -980,7 +969,6 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { // NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS(this->stats); // NETIF_STATS_TX_TIME_START(this->stats); - // arduino::lock(); // p may be a chain of pbufs if(p->next != nullptr) { buf = (uint8_t*) malloc(size*sizeof(uint8_t)); @@ -1013,7 +1001,6 @@ err_t CWifiSoftAp::output(struct netif* _ni, struct pbuf* p) { if(p->next != nullptr && buf != nullptr) { free(buf); } - // arduino::unlock(); return errval; } @@ -1030,7 +1017,6 @@ void CWifiSoftAp::task() { struct pbuf* p = nullptr; // NETIF_STATS_RX_TIME_START(this->stats); - // arduino::lock(); // TODO do not perform this when not connected to an AP if(hw_init) { CEspControl::getInstance().communicateWithEsp(); @@ -1065,7 +1051,6 @@ void CWifiSoftAp::task() { buffer = CEspControl::getInstance().getStationRx(if_num, dim); } // NETIF_STATS_RX_TIME_AVERAGE(this->stats); - // arduino::unlock(); } const char* CWifiSoftAp::getSSID() { @@ -1086,11 +1071,19 @@ uint8_t CWifiSoftAp::getChannel() { } int CWifiSoftAp::setLowPowerMode() { - return CEspControl::getInstance().setPowerSaveMode(1); + CLwipIf::getInstance().sync_timer(); + auto res = CEspControl::getInstance().setPowerSaveMode(1); + CLwipIf::getInstance().enable_timer(); + + return res; } int CWifiSoftAp::resetLowPowerMode() { - return CEspControl::getInstance().setPowerSaveMode(1); + CLwipIf::getInstance().sync_timer(); + auto res = CEspControl::getInstance().setPowerSaveMode(1); + CLwipIf::getInstance().enable_timer(); + + return res; } /* ########################################################################## diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index c49c73ef..c113db86 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -382,10 +382,27 @@ class CLwipIf { // lwip stores the netif in a linked list called: netif_list friend class CNetIf; + friend class CWifiSoftAp; + friend class CWifiStation; #ifdef LWIP_USE_TIMER FspTimer timer; -#endif + + inline void sync_timer() { + timer.disable_overflow_irq(); + this->task(); + } + + inline void enable_timer() { + timer.enable_overflow_irq(); + } +#else // LWIP_USE_TIMER + inline void sync_timer() { + this->task(); + } + + inline void enable_timer() { } +#endif // LWIP_USE_TIMER }; extern CEth Ethernet; From 08097921b99fc97292f681137d643ba80b5dd15b Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 12 Jan 2024 10:37:12 +0100 Subject: [PATCH 54/79] fixing dns resolution bug --- libraries/lwIpWrapper/src/CNetIf.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 16791b03..9d0736b4 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -172,7 +172,6 @@ static void _getHostByNameCBK(const char *name, const ip_addr_t *ipaddr, void *c cbk->cbk(toArduinoIP(ipaddr)); - delete ipaddr; delete cbk; } @@ -240,18 +239,23 @@ int CLwipIf::getHostByName(const char* aHostname, IPAddress& aResult, bool execu // TODO instead of returning int return an enum value int CLwipIf::getHostByName(const char* aHostname, std::function cbk) { - ip_addr_t *addr = new ip_addr_t; + /* + * according to lwip documentation: addr is a pointer to a ip_addr_t where to store the address if it is already cached + * in the dns_table (only valid if ERR_OK is returned!); thus this won't be the same ip_addr_t passed to the callback, + * there is no need to allocate it in the heap and delete it afterwards. + * on the contrary the struct dns_cbk must be allocated in the heap + */ + ip_addr_t addr; uint8_t res = 0; dns_callback* dns_cbk = new dns_callback; dns_cbk->cbk = cbk; - err_t err = dns_gethostbyname(aHostname, addr, _getHostByNameCBK, dns_cbk); + err_t err = dns_gethostbyname(aHostname, &addr, _getHostByNameCBK, dns_cbk); switch(err) { case ERR_OK: // the address was already present in the local cache - cbk(toArduinoIP(addr)); - delete addr; + cbk(toArduinoIP(&addr)); delete dns_cbk; break; case ERR_INPROGRESS: @@ -260,7 +264,6 @@ int CLwipIf::getHostByName(const char* aHostname, std::function Date: Fri, 12 Jan 2024 10:37:44 +0100 Subject: [PATCH 55/79] cleaning code --- libraries/lwIpWrapper/src/CNetIf.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 9d0736b4..51cc1550 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -6,7 +6,6 @@ // TODO hostname should be defined at network stack level and shared among ifaces // TODO buffer management (allocation/deallocation/trim/etc.) should be properly handled by a wrapper class and be transparent wrt the user // TODO the device could be moving and as a consequence it may be nice to rescan APs to get one with the best rssi -// TODO implement setLowPowerMode and resetLowPowerMode in WIFI driver // TODO implement stop softAP and include it in the destructor of the class // TODO split netif definition in different files // TODO implement WIFINetworkDriver that is then being used by both Wifi station and softAP. This will allow to use both at the same time @@ -412,9 +411,9 @@ void CNetIf::dhcpNotUsed() { } bool CNetIf::isDhcpAcquired() { - if(dhcp_acquired) { - Serial.println(ip_2_ip4(ni.ip_addr).addr, HEX); - } + // if(dhcp_acquired) { + // Serial.println(ip_2_ip4(ni.ip_addr).addr, HEX); + // } return dhcp_acquired; } From c3ba2770aec80439cdf6b8fe74380dd0242cb822 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 12 Jan 2024 10:38:55 +0100 Subject: [PATCH 56/79] fine tuning lwip stack and compiling it --- extras/net/lwipopts.h | 84 ++++++++++++++---- .../lwIpWrapper/src/cortex-m33/liblwIP.a | Bin 274428 -> 277056 bytes 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/extras/net/lwipopts.h b/extras/net/lwipopts.h index 87d0d9a5..b6acf324 100644 --- a/extras/net/lwipopts.h +++ b/extras/net/lwipopts.h @@ -95,7 +95,7 @@ * ATTENTION: This is required when using lwIP from more than one context! If * you disable this, you must be sure what you are doing! */ -#if !defined SYS_LIGHTWEIGHT_PROT +#ifndef SYS_LIGHTWEIGHT_PROT #define SYS_LIGHTWEIGHT_PROT 0 #endif @@ -277,7 +277,7 @@ * (requires the LWIP_RAW option) */ #ifndef MEMP_NUM_RAW_PCB -#define MEMP_NUM_RAW_PCB 0 +#define MEMP_NUM_RAW_PCB 4 #endif /** @@ -318,7 +318,7 @@ * reassembly (whole packets, not fragments!) */ #ifndef MEMP_NUM_REASSDATA -#define MEMP_NUM_REASSDATA 0 +#define MEMP_NUM_REASSDATA 5 #endif /** @@ -329,7 +329,7 @@ * where the packet is not yet sent when netif->output returns. */ #ifndef MEMP_NUM_FRAG_PBUF -#define MEMP_NUM_FRAG_PBUF 0 +#define MEMP_NUM_FRAG_PBUF 15 #endif /** @@ -353,11 +353,18 @@ #endif /** - * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. - * (requires NO_SYS==0) + * The number of sys timeouts used by the core stack (not apps) + * The default number of timeouts is calculated here for all enabled modules. + */ +#define LWIP_NUM_SYS_TIMEOUT_INTERNAL (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_ACD + LWIP_IGMP + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD + LWIP_IPV6_DHCP6))) + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. */ #ifndef MEMP_NUM_SYS_TIMEOUT -#define MEMP_NUM_SYS_TIMEOUT 6 +#define MEMP_NUM_SYS_TIMEOUT LWIP_NUM_SYS_TIMEOUT_INTERNAL #endif /** @@ -416,7 +423,11 @@ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ #ifndef PBUF_POOL_SIZE -#define PBUF_POOL_SIZE 4 +#define PBUF_POOL_SIZE 16 +#endif + +#ifndef LWIP_SUPPORT_CUSTOM_PBUF +#define LWIP_SUPPORT_CUSTOM_PBUF 1 #endif /** @@ -549,16 +560,27 @@ * an upper limit on the MSS advertised by the remote host. */ #ifndef TCP_MSS -#define TCP_MSS 536 +#define TCP_MSS 1420 #endif +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif /** * TCP_SND_BUF: TCP sender buffer space (bytes). * To achieve good performance, this should be at least 2 * TCP_MSS. */ #ifndef TCP_SND_BUF -#define TCP_SND_BUF 1500 +#define TCP_SND_BUF (4 * TCP_MSS) #endif /** @@ -596,7 +618,7 @@ * Define to 0 if your device is low on memory. */ #ifndef TCP_QUEUE_OOSEQ -#define TCP_QUEUE_OOSEQ 0 +#define TCP_QUEUE_OOSEQ (LWIP_TCP) #endif /** @@ -738,13 +760,45 @@ /** * LWIP_DEBUG==1: Enable Debug. */ + +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL + #define LWIP_DEBUG 0 + +#define ETHARP_DEBUG LWIP_DBG_OFF #define NETIF_DEBUG LWIP_DBG_OFF -#define DHCP_DEBUG LWIP_DBG_OFF -#define UDP_DEBUG LWIP_DBG_OFF -#define MEMP_DEBUG LWIP_DBG_OFF -#define MEM_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF #define ICMP_DEBUG LWIP_DBG_OFF +#define IGMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TIMERS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF +#define AUTOIP_DEBUG LWIP_DBG_OFF +#define ACD_DEBUG LWIP_DBG_OFF +#define DNS_DEBUG LWIP_DBG_OFF +#define IP6_DEBUG LWIP_DBG_OFF +#define DHCP6_DEBUG LWIP_DBG_OFF #endif //#define LWIP_USE_EXTERNAL_MBEDTLS 1 diff --git a/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a b/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a index adaabfb1cd45db2e25e5800f1377a10dcf103d47..0009e3f547eccf14b47246cd35170fd3bcb855bf 100644 GIT binary patch delta 20760 zcmcJ14Ompw*8kq;%%?i^*OM6Gt?%4HS|7-1Y1`bEN_kExLbI;>u&HDQ7 zwb%ZbbM~I&t?%_s*Y!1#e)n3_t*O@Zv{msDj(gM6jO;4X5kh+t5`X=VOUiLV{-_Ll zjF3MnqjwN8?hGM?S?c1D1e3=R^8Z`r5<>pZ1?vAprxoW3`EM7;f2yF?LkN}zNZ)^< zIQ|=;cVPZzB}6XNw2UZv|6Tcc8=>lQD}YeBaMmrPy=3epoU)AY5Dv?Z>BPYuX(D$mZ5qP; zhr;J-$RCzjO9<~R3wIFy?&SeV@m>?*)upAC@OLX0Hxu4l{yClSP&9@-qUmoHS6ONI zdVlR3e8QC3rKJJ)Q<4_=JcbzgS3(!k!mRarPR2BN*PUv-#Mv8fZc&fRJAMn~gSBT`+yiq868VrtddIobwoMfTV;s)Tw6&A2-KFSRi`@BShh4uI9Mg1`j z5Eph8KYNLe6>iy~jv8teV;1w)`r~32)%syn!lGl*+4#YG@g#@z0|sMGgc3}A$WX5m zs2<8#D5%F0M6TVQCZY;)iS@I z@h0*f8p{{@)X93uKZ)#?`3ay4COye#GM~rzWb%W|YZz}Kmnqz`fQ(26y~%H~0o*|W zz&(VAagO>Z#;205GH+&lKN2JJICX+aI_V|zT^WBb$&h&?;|GvjnU?|_ND7RyU=TCN zB#(FEhmbO1?z-XGs&!Jq{=s_8R=G(fm1R$svV~LF=oempblq9%h=Gc@F@#`59CU0j z(AWY3BM=HS8|o*qz<4Q+zt}=T0%W^3Wle3Eecgq6%0Fk%xe=#R$v-nl0OVE1DxW z1n!kt1LhOb7wlu7BqANc^%0WZ9HQ&!uKICrM)5+$TPL-v!6;FfRURTP%;WUEj|LH# zUxY0zSRW2hjO%GAIQ~$E*DffDLQ74A=`&Wp7q0Vu(}3@U_Z&wvhT~!+-2-oL24 zR|{3({gcXjg~HpU@a_f~1Jm|igfZ}EgP5_J*C(%5xFjiDOe&WtLi`p(WE@D9ja~2c z78h-yarA&NYl|Uspvq`77a;3WQmzAoYNd z$415s6~b->LT?4aQWZj>FzH>xfGU;u0r2)NP4_6g*Q>m@3ANz8M&*4*(f(A0cdg3% zkU+N@BHveeU-o(nRa@f(_g0NCZfmHpYikfrIPXwNSHPZA!G=P9yRr%Qy$V_r(t&WV z0^z0#ApsDKEUh?_1p z_V7On1~pJ}#dwjA(>~S>Ohh`BH)+$LimBqPNE#ws+!oaSAmZ9M4WFp0J~%+zWg>fC znY?3xrd=ePm42i))262P%SaPaqkD!F;GMAIA*Pf}u77@466dJ+FzdI7{@RuMrsYn1 zA}S*C!58auRyTeUwK$qs=r<27t=L11{?QLK7AzgJ)YGQ_P-APY&Aw(W;Z_FaR@c3j z6LRu}oMnxXHlr+IUKC;~=rjn`pJt(=zprTIcED_DlcI~FACFLQt(({?H`{P*Q^4@~5-j{9?;?wei9u`+LSlSW{rh5`&#<8yj7mi0D#5uD_7+Rk2dzzra~yG!m7r8 zG)Xwv2#i#(iVyCSlIL-ok->iGj{?zXoE=*n^4MCfwMU>~N3XIr@9g#kU69zxSMf znf4o4RGa_&j&-)E`Lu6T#b`J2JMAG^gBso+m2M}!v)sj1zB~3@bicIDL#%H(*5>dn z7wj8sX|^kE35zz(<5E_8a;%9hS_`@MPv>gSYXzh?ac_lBYpq>C_N#M!e)rrk5AC(u zv&Jgq1UbIk=_%5aWa56_DRl@jXStt~KWEiCTf10Jwb6dx)CoCDz@_aAk`%wlC)vNH zWcfEfJ|_m+6Q-?;GFz53()25JQ=STU`}r7}HOXAFZ*rEq**W_9@3TzP?z12FtR`PX zksFC7{;G}}*R?rW*FJDMXb*HODKDu-sGT>n^y{MN&)Ky8=j?9Wmr_WkMZ6`; zz0K*Zj5~>~+73Y;_tX?%F3;I_T_xR!`z_~TPk?notqCS3C!BkM3a0KvD4u4r#m_)H zQ<>3r!LAkXGfAlSkU_?gwc2&%?f@EL+cNw$NGh>7t`FOuYkR28n~&#OND`#d3hgiO zu?+dmv7Po?0{qj$f<4j6Gqy{18MUTz^ex?fZYHq|xjt#TX%S}$ZQglvka6eD!PfhP zJ$sTJQ(jz~V{VMH%^~aR#`x9$JhmHjF=|J-+BSRgiZI09Z8XW! zw%W7KnlQ@eA3QJR&F_>{qp<-s7|S{<>55KQj(u?4v%;D*4_aRk-5^2jzYuRTmaS<|z?Kh)*>Qc>2mjM1Y>W&QTK5K6 z2ijAhr`;BxQ)ae>^Rqp%pMLGBq~DH=6$+0g(k5Zi(R|_LQDa~>xZ^i3d&U*^tqBqQj_I`s zI!FjSW(k9bJEk85lp~o8GflX;CR!*wruRX+04h9lEJfILEGvA0Y-|NYjtpbQp;Y(< z)aK9nIPz7&=Yx62#gmaL{YVB-*={nj{S$uR$!L}RXqA3UXMG+S!vIgRWfN^B1CN4N zBJkwF&H%t;gN?%DpGS^;^WEWPJ9BHF7vpB5ll>Ep3K8G4e*J? zDf4)n9!!$RN)Gl}Fw0nQKT_;u(35;1^L`LjFg&^b1$gg;0UuNGc=PPNP=87G$3`JO zm2VuS08>a95A8=~3Y1{di}aBV;It5 zL&*u1|5X+5xGg*2S`na?8Codx7g75_f)7*HaVU|0=4l=TQ6M8*r^ahtHw5hi4v)eB)KLWGZw zca4`0Ps(PL%Eu`9X<|v`Yy#&zeKPu5@2$^0v6M!5&w3 z@ZQOO|Esehv+`_c_8dG7f-|N+I3p6qo(%KvbTT9y_&QDSIhlm#LPFrz@k0Nv$8s}f z3&vAnj>Uu&KnA#Fm=)OgTO|!*-OJL(9`ZI>J{|1@{B{7lR|vtqBM$sAk+Gu0R%%S7k_RoA@h*}{z9bdKx>w=w9zLMMdf8wDQrOekjPy+?Kx1Er0#vt= zkPPG@Ko&4i9CI8PofLI>fTa!cyv3Si;w zkB)VO6d~OywM6G4_f|oXhCDL>x<}sBg$lw^zL$_GGQ||5-9nizk?DG*O@zFK6fz7S z3Ac}s14tpj!$={(qquHkgcv|97;;D(r9Rc|m-`eb&Jx_-W}Ci12caJTWFZB>T%^!d z7&ywYi#W(A28?(0Uy;4$Sm1~8CbsQ2QO67nMQ&4j>AWH=Zg zj z2UlJ1S}&~lzD#hP9U&zBkQ%Nu=s5ilE_~lpFttVsZLRYJ%h@m?{D*GBgtLzbgIb>z znp+J*U~9Orx79~@_=o#={4x=KD5d_Mcq#B=fu0}k@0TFWnPOoKa8}^3QN_YW;Ie?j zCKn4=fy-;R%>J?5zXCWb(>44!+L;|1H2tC{-7R`|oP!T7Wy;&c(M4_dnV0 zH>>U5plTQo@Q=-9AS4QRwZ&FD)ubzT`dYyWGhGa&I~43a3=@Zy(tVJys?9*R3bQVT z2eMt3{`RYvde zCIBK%5*O{~qqWPJF`o1E;W{^A18Drj)VFDfIC%@49Qm1~>4{CpvE*&K_ZZX%WO!`> zMF2Zl$pS=W^>#pDeF|17P`n5eR5kAeMG7`JtV*T%4m81R3wV(VyF!7j+!tS~LU02@ zE<<=#g)kowj1W~Z6y@G{oeCih_U1=11ibTBwr>p}u(1aS%Kh;pDug9~(9AOQR~5n* zKq!)9=m*rBp|dK4agc0wsF(Sz3c)Y2Bge|kblmWU(a=7=9|Z)qnJyH*r|+#-c-^b0 zSH1mh2d@~`cJ&r`gaToJ0wIU*T<;P<$YX6E3>szjjDUdSsu;>Z1p+=UC?h`#2!j|x zu?is%5WJH!Q-R=pegH>y`T4^7!A5rG(<+D}fN+8l1~CMR1_};YK@~&>2w4Yoe@TVV z3JBgoo-OqLC0aY!Yn!=IWqVO!J5*6yqpG%CK#&9eSOwt*2q(B=z{3;}XH*cCkZP&t zPO1RS1Ux!8?0#!^VqHs6x=d zZHif>;WQ+3oC@M3Kx_b4?2IuAh?y#gUS09zA6Dr5rl}C-_vlFFg9?O&GD2UF;Z@L8 zm{1WOv>e1Z*q}q$wM(FGL(tm0O1;mB9kyfKhOpf-uvfYpLgTQHf{w@%Fpw&7 zcK~jojEncRUfg?RZyW`9>AQIkyfQ!o?W>UFguKuV54-{ofI&qdAtfMRC2Wj}_DO@U z^iMRxXSoSlzn-{GrC&>IKgVK6TiVpr^t23iX4MNU;A;QjT@R8ZxULO!@MT)tn(6?y z)wXU>o9{4c^|42zI`-4Nv5f5tU&RxPw=<={`$H0{^%}s z#Imc=83mj5#@&rsLiZc-j?88K?8VdYwBfU7@z{f0``fcEQ8bxc9amKtYtD5>5p&bE zQB~tdRM&-77uaV+@zt=Q9}rd*W*Z;1t}dtgg`6h$y{uu$1NfMEo|vF1%@_rOK;c?3>qUskYm58~LlZ`&p`zrIBhVD* zwHw2oUqW7EPFu=?qf)A*;QmeJHIjw5X?alj0jOqsD?5JM^4lTPoA>YZOt$(j>yo<} zXvy+Ot>ebJ59%6<8cLR%u9K3I#e%Tv@9~ajFNBockk4usUZ{@Zt2TIaP1SY8zUKmV z_1?yk<=q)MT-Fe%RJ>p?P}3rfMbqeOGR?Kv z%{D1NrR7Pr$z{dU^6f&-N6jV6Px<vmdBGG4cP)?7AsG-W!RwF3ix@>_z*|3eT$7G|D^?o@0!z2 zc~%L>dofgV5izf9wv-{JrCLJNGDPo!J8)TFdsJ=-oQ)-{{4&RJW8QX)Jz5?JpZEr! zKn@0iQ|e;k9?XUd`*{X)VVlZ(jKYb$s7e~tfmXlfP4(k{-%kAl7B{ei zQa>T&mWwVFj@)X1Wp?R5SJAbC;a?xaPYAyJ*W2`5{es&AD4q05Jx!!ztVKG*taPizuDhf4EDZ)Y`6@2*siK2HPZ z!`BT5PcaEVE5&^uQcDl0#$*m$^y#47AmST#8gz-Wfk5PaImX_ zD!VudRDsXSs>|@ez=_8+)X?`Z2QqebWtIV;^73#;Nn#W{B3<+myZ*pMi4|HJ>e$xq ztY_P}xMw6?dIokB?oYftg1Hquf|=XFCI1Wsk9sHG0XFyCFl`i5 zed#^)pg0Lhv$zV$*Wx}P{ug97jd=DPX9((CUmUq6u6&Hf_3kV-Vyx_9VG!UI7cW-j z^C4o)Eoy{TuKWpp4tSsV$Zb9@eyr?;#(F5lDt?Ce?P5Moh#8<44~*jVV#ZEhPhCRo zGa=#nH4HnY;nOO|Y85Z2_zfx^f8yu8u;PzZ{1+-7wn^LTXSwPa^HT2chTMCx zwyOA^D!#9Z#~;UeFZ3Uw;tP4Wv&a0RGMEI5Z|Z1DFueCPv25m?(%F@`*EyqfW~F#Q zN00WMKCi4|qP?yltU^s`pCB+V=aElaoLGi67aZ?v+^k=`?FPUCCQ#{{= zCW^fRXuNPu7ZN7PCrRg7-knufUI1N19cBoM%ayjXIe1*PB0oYtVHge@#=zt6=KCXk zL_R=(g9I>Pa(w6|a8(JE%O=E#ysvz^1vE$InIG`Q67P^43grED2&4xp9+UUi zAD53f2Fphw@RSvS`iZg~RLlU22!Ver09;ME3__+Oh21mQS!XW<%!V$|L9JVng5M!V zVQAncCknoksYj;xQUmv`D5EGJRI2 zYmkB;ZiAv-lT44w^ar301jL<49dzI=Sz&}#9~~b?I+YNoOjjd?J%=4K|AkC%A%#rg zR}rROk8~jH`Xhy|i$Dr3?gbPB>5mj}3w>Z}qGP43cuuA-%5*1E&^O8aMW6^&3>C&s zmc|6Wgz*ga@ih6Z5U7Clc`;-V<-nhp=`Tnjvp5}*hT@AlXke84yaFjWJ}c7=GPOZp z;oBcmkV3^PkirOKeLh3(bLdLe=QHI#&zAcf`kwVUj1AW3FedOzoP)u9)PWz$VG|Z9 zwCp%iNF6)$sgMtSV0N^k9Hu9%W(21vJM@9nUPe9x#sZF&S+LE3bT<5O6Dc$-3%hg< zyhno+=H_~&a{&+OlhFUa;D>Hdun*@!N|4TnU2midU>!gThegYf!nAx5DNIYeQ^3*P zj1*dW94WN?BvNSc8Kfmp5z?n2aHMcwbP*|J;xf_+(Em7SFaS0NAb@9(hX6i83WG4l z7bvvMigXcdg&>6vpN$l{4}U1Ei-y6A6znu`%Yl4=Oz%VLg#8ty&|MI4zi(bRAzDVnKguaIFlc zf2QJ<4EmDT6iO5Q*TfNG1W%KAB^2&y=8HjL)a1Vlq%cf~Nf=okr#%m!7Q$AUDbVee zgTzm)+62FYD-!or@CI?`CaMoK8)Yz1>x6H!qqQ3-q!M@81bvSF@jTGuH--rch6{s< zKsv}NC}2pS580)MVS3rifCTOEIspaJK(e6VHQxw%1xLi|D%M`%qP4dGFHIZ+o1EhL zE1W*CAVHcPXrdSPY>w7iA<1mxFX=YOlyK%GDIBy7hQh)V#~5gcHVd3I*p4v#?GDDw zL%|C*6n6oI`9t;0E>vuJn;L@DMx40s7tW+WD*YoQG4X%kWl~n9xau+&iig^Fpy5_$ zSj}BDQkZzIcXyv1chN{b`|hG)TdLxQOscuFK`ew;aDsoVU%mN|ey)EB#E>OemZa-1 zA#C^ZIwZ^rp(TQ}5O*)Ni7_zz@n`xbtrfc9rZB5AMBElhJASdxwlKvrk#rjO(nGGi zDEb-f3|tErBV*_(+RgQA4E>N&z3bgr+RexEn$^-U`nq%W68Hu3X3rX9$?~`}*6WTO|UKdjDp zJ4izCjoG*{1Ld@17K7p0r=SxbPNrg?z=dNt2u^&Tk$IfeK_r^2l6kbzLwQ3y3oqh| zw{G(>L4Q^0K6jnXqY2ckdd>5XUc)D1>jN~*6)}Pq(D*38)(w$X6J4hCh9+m0f8LY@ z-$deqe43Ux3=jQb{j$Ldj&!(u{GTV^YTl2tI(sk8baj1zKF84=;wz)*Xxb$Hh@@3a z9}UDUE(O9x=)|u^(@|WWPV7-YN5Kj;w}4t`Ax>X$X8}A%R>0C}6+bP20q2IcCW@0j zfg9kkF|;QQ6*H0S5KEC{h%13;GhjVpQ$##EhU!83tyh}CKx4*&v`Oqe7HlipZKtEO zQk*oG8pPH3`4{18a!;)p=EM%MWh_*F6264KhS6@K9PzR;`TwA}TM-=~K07G1TmS*c!HDA9< z9|>ufxujZ7_;8A5$igJuU4(N3?;<>?R|>I(5w7=xxwMXWTw~T_Ysw6q@|7NDI5M)6 zp%jpRtP)Z7ekA@*?@W`@TS{(C5AKR@dlMzu`aWE;Unf~a{i0Yqb&bs6j&}5*D|;`* zDT2_~wPhf;PoWv}yR7kZ-5jip4rT}RdTSQg?nZzg{&?KBJjz(Ks>TQX)Qy%yRef`YVu9TU79>{vC>je z+3U}Bs!W2oRDBnS%#}(AIln7w?qYdX=wvBnELFUVuxhPRs0gd&^-f_)5ZyN_t>qld z*sK&HguylL9d1m=IF}83Z|`JS)r*g)?;Q=DzNqdG6vsYPDE`-%Oo4XUbn5DJgZryuxH9YS zg7_KKwb;WQ>d?4Avy_T`ZgW1aGymWYc4!dI;A;9Om)%i=WbJy9dIM1KoxZrA#o#5>thLnhtquo@8$A+4#W^GvR{;Lt(t91{; z`-I7GR)MxdV-i}P^s^1S-YoIowB3{94_^FG-P;lSuUa{M`m1#S;(xwP7hm^}t2f{- z`QfZkDU^c+#`E<*PQ={7wAffWX6eD+iAu zMxY18tI5>jn!kg;?CXzDS30=2ixFq+;^X{r7f_cEHm+B8@kg|9<2z|DKbme9YxnXN zdYIi~x%a}J^fr+;@;$W&;HFK7Pak4dBS_DSV^E6!&x)BzYfySw+=x>ADIxpMD#TWh za<{_8YmIylZ4BI|tr2VgOhfVRSNRkeDrPrZ|KY(nWyu?3~LUlPh}_4`4( zTa4ci()A#BhT$X0h(ZBLb#!X1TI|<&P`wI)ROFr3Y&M2~S_He%&-(JG*-; Z`?QBfRat~+ delta 18172 zcmcJ13tUxI_W$1J+>3B|czM4BE?iU)(W{{1Geo?a;`^CeqKJYapkmsj-AieMiKT7x zm|CNaHvVQzfool9EYPg9Ordo0Svs2d8V4M-TiN(uYoBxBaI}8^`Tsw2a`QcF?X|vp z?Zfe{wHO37NP$)<$6tV9C@~dUu z03y1}qC6u0R@uIch;jiZxA56kB0j2on@vP_`BwrFq3C>dM3;0+TF{S1u~$2JIAZjh zM8|iYdjx4xyw0Ef#k*st;+)wtiA= zMehBgMJ2Mfpr9y+eeM(0t}u65$;|x4?2>mPJ9##O#rY&V`uP6M;N?CQTb$o^5Ny=( zdiXJ_Qbtb^?9_3i!)IzGx0HN)=-N5bO`o*Z^ljF^sQ#nM_t7*hu@?jVyg~ZLmb6Z?|QeY9EEeHQM$=-GC6y>fhy|V$YryW(i9OTpkQ3dP4MYVuLM#WRf9l!rGaR(`!8_yZFjf8qNB? zY7U>V&dc=Rhkrk)vU*q(s!7*R>P%LY53=W8?c@DT{murR^@j#Kp^lGV{ZTK~UK0J- z^Ya3v^fA;=GE5KyqyZB|lT_gnjcmZiXlc+bA%JCl;U^X1PWi@ky#<;-$qsHzV)r+W zmPSkxO>Bge?)bAL2yjVi-9(a3Qb43o;-Lf(4+1B*mdyxz6QN)|b}E2)k~~HB;IbE4 z)<*UwuPAa?Uhhk`D>8Bg5WhI`ZX1P>)F|>~ZV*6@N=uq)jQ@E>jTk_JNP|TGDFoUu zl<`~@LLLCRH>CH3O03832aqrluE=uJ5yY&>a4!J$k)*34M{~IY>D9(Qili%Y9IuZd zqbPwhItYijB9_cSLD{g8r`r&i$r43=3hDw#NAi0`#xV{coyitO)^RzJ>}*q?MD{8& z&Orc4CI=`?ALvK~S9B+zDFz8#?m{foK*X z8K?)@gxHRdL5O%~23s`9xNxu@d9WVWJj&c}9xO1Fr{G*b?1mhrp?pH(umS?YhR{(! zd|Gh;nKx9R^aQ$vJuoaJq$gl>5n<~mcVng79&?=CW)P+4-wf zPVO-JUV#;c0St!XA+3IbM(W>(-BdIP-VA#%mplLfas&6VM!L3HGzQ;N`FcSWE;vuN zaA%;t(QU}K?ldMhtL(hpc7SzI)b#g2?kZjCstfg3tK&d0VyjWt!2ladhl1OEAclWD zct5GWK@60NP1IB0v&91sX0?Zpf2)U4qF01SeFhj$=HpRu-I&}#WdIW*_X#istl(eE zP;3I>Jfj(bQQcur-9%SlFoES@C_yahMx?$3CT=`$VeAc~Zj{vydKK7 z-7qH4P}RXrY)k9UKpXI{rS*Hj$cIFVKS7Op4-qCF8wh?~V`zk$XkN2RQ_~GOHmH|TqXLw%2a8fl6-Bk>dhT%0}NZ<@i z!*E5#&_l(rSHtiDFm#dz`wBr+V7GUM(828PUt;tZLG6dctm|(7uE6D9e7#g$-)XpR zgOiCzb50YD4vu*@Lmw5xT@8aDtTDc{Si(Pz$v!HtzA7(oSmf&EQ~+KBc)RVOM!g_| zR1E!93~?HUU2cYc(He#hz~Eky162&E3WEi7xLxsJgJMGh27(&?70XKKOgnZwvy<;8 zxU86z0{cx2}WDED0^>W@e8!LzSeITDR*6j!bIv^0ttJ}oXOgcsj`?8p zcP_$G^1gH3e}Sf?WIIRxzG90tVj1ljQA|3Yagp=^)s8U(^GI@fwT_lBT0N#c_1JO&(_P22I-Y07rm3tHPDoERV-trYlG$b zSEOU?3Xepu`kXcAJUmXNWm!mzdso*gmHD zr{(7PJ@Zbw){(Cw$lZ9ecyIp@$ItiwwK*gGj_qyxm_}+qXY&d%DZO#8-AyT+#<;8O zChJL8`B)sZ%Xy?bX?(~2bM^;Kq`h~Y8D>ggmtUsL97Wjd`DSbE0<<&dqmR!vJ>x?i zSLPz7QI+~FMU6f*%(`pXCKx%AWNV(Vcfee0PJ`T6lJHtR=?KGRfqstlNLq86rmO_1 ztYO%_e=jn>!ZNnj&=m7a`+l^T_WhV{*_`p<-tYFxzG;=_A|zb2_i`agdaSu{uX%-# z6jZnG#{pnF$TEyYewOIB&(*Vbb4EfRKY9eYTEt@-0U|7=Lf>jG2RnB;LLfj<}C%!{w? zpDkYOYW+vv&a0QRPq}>Ta?Mcdn^##=co6eE;={6P#ztFUm5VD@RglD9b-E;4*Dk3? z{p_NM>bSL4aG25ejFS6deQC-&zg1fzRJ7R5NkCI z$KjxHUToyY@$61`BrE@TbeClgVzw65x$I+?J~w3Eg-UAeX(jo)hUu*rtN-fZf6Bb} zq|2V|z=k{ycL}-J;M?m?T~VV>KX+bZLs4UU{XZHAVVQ@=(;OxpPG*@$;@RQD@xJLr zp4G&Z_93=e!0sMS416%m&#JSMgmHD^3PX}tJ+&sV%9=>u^5Qy|(f-NHTdD_E#;`Lr zokK#DNQ0qQrXo*%NM9^u(Y4RBE43f^ZHgnY@_47;IX{8zKG?0D-4Z$SuxlN=bZ|<1 zwr95Ig9l-7#lW-wdAQcVc3}ZY$LI4J`7bN`@C6Z0PR#eCD7um*eN-BRZroJ$hi$DL z&T2pE&GL@qQQ|mpv7#TQQonV{4@tw)@yyZ2p%aLZcwPvKfYc>zC09 zi3HB#sx6UUQP_9N{@G^CRTZTB$xNI zrsGL$#v70tIALTnPMCb*v4mgRIsgjnjT7eJ6^aI*@&xi2=TBvoZ$z^5CyXA*>O>pQf>&p^={?S6F3QjKk;aJZgjc8F=uGBE6IwES#7C z5={mvvRofShPA0Tkui$w!|h|qG)0Dl0rI!-fe5`M&8j zSEmlFK0T%o{#}1dw5*Q8AF^$4NUF zFB~1rzy**IBoN0>*|3358aYiPXDI%|!8QO+95WPIUNfUfv5s`$4d6Xz037(M6#^vp zCsWwSZ>)Yiu|3nBxn?II6FvHhk-h&-AUpp}xY(m_FNf=!RkS6E?$we+XD^-WBraN9 z!v1t_inlg@&dqrKoW-2$XLvYi-se9}nv(^&3l`^=w9TELnd;7+GyQp^?Rf&dgmc4- z*k8yQl*7A8#ImZeZGWg>VMZYG?n3T#u`wei(!1~t-&)g#a za+EhJ?Ytppd~JsH@;gg(*s2(8Lxj}T4n)W};c*nb2@0SAjC!LC0rG$WalH$FfI6(- zE@#UyAUtyzwkd&uJ|5+_l@0w_BbAvmEq6uoP+o-A=3~cKs(|d0(nuu zy@aGeM1~4T5+PPXporjq91;AlA%b5cpio6fGvYErT!;?HQX#H_Xhb;Lgi?qU);adT z2XUVgF%VfWVjxaMgn;neg$>L=e4h{)9NrKfkcRi<{FwoIepQk0DD_4N9QlI~fjtX&efas6pRcxqHh8{3gaY#diIm7_a&I8Z@ zt2Y4=?7As3+8L%RDOjk-Qw+*{BtR}!?4MEWS0Wy?!3z}JfuX{o#t8Xb!6M;v1r775 zfpOzg0z=FLu5Cpl_zTa;fn%WjDEUl2N(|85Y~=q$o&p0blowDwN=O-^4USjv;m7Oe zh%k39Kpe9Bh!7CLz+lL9h_EKGK}@4ZC^$f|OGgC1OhlLmPsHEDA4HIKh)~b;7U9zyxc>|nJWgcitiKndHme>xzy`C@M8#1 zvBw*RdEEjD8+eMn(J;(6C|0QhjVEi`5y?ESC3wYy7CZ42>w9gOS67f^kJZrbZjtgqI?&=*eWMRu#hPvevWYi?{27%m zkhn^5GqLSAL#2IIYNQEl+|5w`N{vA`H1My{XnV7!o1wv&hlPJFxz7wZJIP7q%bJ=j zsOiVkSl>a7I*oNWRz9Ym0vXb;~7jty9xkdh;#F8eaqBu2Q9g1`h0`v0e$*cHqVK5}~-; zbKhmU2Q&zR@4$PCiCuMjI_Mssbns46F-!+Lb;K4h>c$x`v8!hA0R~*#7(=p(VX=nc zDPSnz3`H7-cvTGQcGJ(3@37>a>`zhxQtfrg<382DiT-n~=|r!)*lfZ+&_pqk#24Cc4`>XfFTUWfq6C=ledDG zdj$ zlg9?f2KrBj8svf?`8JvPH;4Mqf0QsIiq(&gRg6}E1|WneEh!G z@Xi2U_X%Q}iuZxSfTuv*DuCg4(%>R7$f$4odZY{6ez&vloc4rVgrzbQY|HWOh({*e zl}I}FQDvNdA2briqVC1FzVP7R3Q5&wniN<{<)kB=DH&Kg}dx00B{ zMkU#k${ZOUU-2|)f~!tQpmj&8T|9-UOZcfisf?yLGVYzldYyoOcT{EGAmWy)Y0;30 zwI$%IjKyrv522V{xe|74x3oL&B5%LLbu&Ae{&D5!1! z#%R*`vi;=s;NxBLq%pg13ZDBR4Nq3!+k^gj#&a8n>gxC06nzeW*6Z9`L&NL8b7dVm z?;^DaTz<9XL;cTu=NiE3UCE+nsfE!WrziHy+Y&*NOlNaPLZ-YnqRd|9A93toC)yp2 z^sXXF`)lkGkUcjYsHtVEevGyCDND+mJs)2IOf1EB5aiC-()tLRNSgYUPK{2>v`3JH z+B>PGStC|gg|3ENxsNR(v^3N@HcwnVJz`5$#_E?dY8#_Uaa?ld_sdVpo{-%oFK2#z z1WByD)3LOEhzVW}9n2t2F{PU`(i=OJ_8rqd-|6zSZ(0pLEb%A*DHeOmSN-$3{NUqu z##8 zQ&pW^owLT=OmcEwe3vEPkDa{rYGD3dpNH*2r(g z&RiV=&EVTH*NY}A{2c^<~$fA1m_fW8V&bA zjVns!F8NwK>vEhPj1`d7MA>h3{z z(my&+dCC;iEj zcAObkdAVpyH8KAgUjE4S_~N5<_c?eubha{Q4X%H$IwPOS+sa!KU(40{qAT!vVXWSP z?@e|MGdB6Qf2?`#Zeu0*S#sv#tE9~y`cpYlvKI}1eC%$SdgPTPYb>Wa-@xBbjK%j8 z9q8e}8nY_oBb2zVMU-4|pE@@w9*) zd_7W1_ol{RyaT}tLprba(rS%&QH&I*&Dd9x2sAb#GLow+qhN0z6g4 z!G5v(j0`f|0FVtT8S9%x_EyJ;jXu;UnS5xF4O1EN=Ewby!RgQ~qkp4HM*jr&Ee`SH z{Anr~>+N{O;hS8)O(k=GBvtAGq~}tpuVjZvs1GaM7#W2&ty=(3E};zPZ$hQ*xirxK zkAiG~U8f`vJ}Ue0ix?@}ml}OvkZbr8C6(&+LZF5)m_Ht)6_QY?2?(WHbY+UG+>rlV zXbAEle3Kgrg@)>T$4DkWc<9rNrApXa7b;L@+{mAU)oP#?UZn@OXf3QsNmQh7Oh9_0q*i=e=}Bso6s? zN=M>!MmWGK$HUVPMrwf(h7To)0|jM6wqqLkf=0e4{rD!08RxBxE_$L{phk`X8OI0< zCbN?@^_bpwZ|I*c4fY4xsTy^zMt(*k+ch$NX5!wE_J5>LUKL|(pJ>$D-25#~{SO)$ zbMx*EY1?b$D3EcSur2`q;^)%&h23&UJbuM2{ULxxNOb}9GwJg{ni5;EG{1OeUP)2m zVp2SN$=sPa1-bHP&x>>C&78X^H&^lqqVYbwZc*+m{spx6nGRC7AQ~mn)70eL6hsSn zu08=;6b8u&GXd^(EhuLy`K!T7;taApoj{M-+1?6b)&^y~3qmXa6h_E-D&*t#o{93Kg$=*1wTVecYF&hbiH4h!&Zj%!y67m)5pCDurj1zuk`3@rZ z9a8Ws1|1U^K`B@LiDsy8Ar# zY?hKnhJbiap@(Nt5AqcSZzBRBt`tPf@L|14!D2-4dqKf%3R)pR{5*6nA~cMF<5!`( zF?%Y^fxA@1!G!EX%!Qx2Ai_u-K!g#fMT8MLj0huh1QF)&7~)(=8zaKVoJ53?IgL0E zK4(OPHE|Jf7<2>?*48yd7&+T5+<_sPh(iPu{yW5cLio@@&(d`u&xg4}d>S(Rh_E0o zA})Z35Jbp*8sO?-D1;F~EP_WC#A28d#Dy?rh~o))1rZh_UVWe=Hd2Q>(9@HMxez%b z^cdf<ZlE;o>|T zaS1G9#Ajgs*WpemBuf#&Q0FPjJ_`0jTndX65qgZ*J-!$bA5*;9C*r!c+ocd#4d+197vW2=S5|>WK&jixArbF(NFMlZt#1F(1C%MO+3KYPbww zAYBom!EBhqXt4KzbqaILKN%i%$yfSYB#m)~bfABtQf(Bi5T-^-AKeu~q_SwZCYRtt zmQ)c9U!E?DgmZ=De-9FQS$zbf{vzizQkp21z@A zqV4r{U;ya|Fkn7iJbhsv__hv?1sBf`2JZs}1W(d=1^j_0t~!bS03L^T8Ykge!E2j) zgC)kd&*87ytq$C9p~r&W4+`4BSdza(fyP=gjQe2_jo5*JZ$YbO*cBta^@9)+jEQmd zgpuRh5%Ay-#lh_#QA6?ZH#p)EH9^=4vn@)Kb zH3Cl)6g{FwC(Uv|hU5`7+($}(Q+zmN-jGy+A0y*<$n1Ep@o?WDJrUr}K;z{LwO@xqc#TPyM@qu>lg8{I($h4qEBpB%0b~2%PJoMu2$XFeJiIIaI;gdLxsH`r-Tp z~h;RwQ4Cze(AzQ#TES;YLerH+in9jbKWyCMYW1(-UeBJJV zRlFA#s##wS@m<0tD=mMLwth^TB7JmC40XQyB%K(dS~&1qGN-A8j`L~NIpKG1FHq{;u^WY$?t?@6&&_{-l}t#)Uc$)X~1J?5WOw zpQpoGf6bQa9DR|t^Pm=K`zJKQS$vh2QfhJDX`o+-EkBKB3+9A5FWjW*#+E2krRWAB z%sJ>jof6opbiUPIXhVKGpshS8q^Ss5#+J}gdkK5uSo1zoaH z=ePvnNb7gXsq)9m&h1HUeG8M@_)5pqpc`i`!p(NA-Sw{ubzVsm57Op~iUB`V|l9dB-Q&wT;O<+h0`MJL@|MrPO)nC3O#_9wwOP zH+P9Jei<(dU$pie&FwI)Yuj*uIVithr*2T@Sn!7MGfQ z$5pi|zjHoq{8Tk5#x^y)Uv+U}A(grrMGt3rpr~3d>QEX&+Bmu?`>56o=%Dj!qeRtt zr-cH}6IV^5YCX&22W=00h~o9mY6@liu6JppY-%U2fweWrp|HG**sjxyZe&uUv;wP zY(w`h-lxY5YZSfpHwCXlO%}nc$>_DA3V(HRsiErUdp~;o9G+hOfxAt zn0dQ_BwVPUKR+&W{%riU#m@S_K|bGk;9c>EkMA+O7lS)@6W|f&`VYiVPp=TzHw?#n zs>(xRjMpPIShr}=RbgZ=Vh&Tokpm&dmN%R=MgGxOr8fk?z^r+aG9+4IR_+A4V zd?J8bLt>C(ec|Vqmf&Q%EerFRjE zrBevYq+bx~q>f(zjFmSl%N;8OLA rc%b!0&I!6;0Um0WhU@&a?s8-Be?ZVS2IsWFt;c}ees*u&Me+Xt^3Lzk From 66943b8e2d72755371d36398359c8b1594a62edc Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 12 Jan 2024 10:40:04 +0100 Subject: [PATCH 57/79] adding dns resolution with lwip example --- .../examples/dns_resolution/arduino_secrets.h | 2 + .../dns_resolution/dns_resolution.ino | 119 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 libraries/lwIpWrapper/examples/dns_resolution/arduino_secrets.h create mode 100644 libraries/lwIpWrapper/examples/dns_resolution/dns_resolution.ino diff --git a/libraries/lwIpWrapper/examples/dns_resolution/arduino_secrets.h b/libraries/lwIpWrapper/examples/dns_resolution/arduino_secrets.h new file mode 100644 index 00000000..0c9fdd55 --- /dev/null +++ b/libraries/lwIpWrapper/examples/dns_resolution/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/libraries/lwIpWrapper/examples/dns_resolution/dns_resolution.ino b/libraries/lwIpWrapper/examples/dns_resolution/dns_resolution.ino new file mode 100644 index 00000000..7459a02e --- /dev/null +++ b/libraries/lwIpWrapper/examples/dns_resolution/dns_resolution.ino @@ -0,0 +1,119 @@ +#include +#include +#include +#include "arduino_secrets.h" + +static char const SSID[] = SECRET_SSID; /* your network SSID (name) */ +static char const PASS[] = SECRET_PASS; /* your network password (use for WPA, or use as key for WEP) */ + +void application(); + +#define BLOCKING_DNS_RESOLUTION + +void setup() { + Serial.begin(115200); + while(!Serial); + + DEBUG_INFO("Setting up netif"); + + Ethernet.begin(); + + int res = 0; + DEBUG_INFO("Connecting to AP"); + while((res=WiFi.begin(SSID, SECRET_PASS)) != ESP_CONTROL_OK) { + DEBUG_INFO("Connection failed retry: %d", res); + delay(1000); + } + DEBUG_INFO("Connected to AP"); + DEBUG_INFO("Beginning"); +} + +void loop() { +#ifndef LWIP_USE_TIMER + CLwipIf::getInstance().task(); +#endif + + application(); +} + +// application stuff +volatile uint8_t state = 0; +uint32_t counter = 0; + +char* domains[] = { + "google.it" + , "www.google.com" + , "arduino.cc" + , "oniudra.cc" + , "youtube.it" + , "youtube.com" + , "github.com" + , "drive.google.com" +}; + +#ifndef BLOCKING_DNS_RESOLUTION +void dns_cbk(const IPAddress& ip) { + DEBUG_INFO("%u DNS response for %s: %s ", + counter, + domains[counter % (sizeof(domains)/sizeof(char*))], + ip.toString().c_str()); + state = 1; + counter++; +} +#endif // BLOCKING_DNS_RESOLUTION + +void application() { + + switch(state) { + case 0: + if(WiFiStation.isDhcpAcquired() && Ethernet.isDhcpAcquired()) { + DEBUG_INFO("dhcp acquired"); + + state = 1; + } + break; + case 1: { + DEBUG_INFO("changing default Interface: \"%s\"", counter%2==0 ? "Ethernet": "WiFiStation"); + + CLwipIf::getInstance().setDefaultIface(counter%2==0? (CNetIf*)&Ethernet: (CNetIf*)&WiFiStation); + + DEBUG_INFO("%u Performing DNS request for %s", + counter, + domains[counter % (sizeof(domains)/sizeof(char*))]); +#ifdef BLOCKING_DNS_RESOLUTION + IPAddress ip; + + auto res = CLwipIf::getInstance().getHostByName( + domains[counter % (sizeof(domains)/sizeof(char*))], + ip, +#ifndef LWIP_USE_TIMER + true); +#else + false); +#endif + + counter++; + DEBUG_INFO("%u DNS response for %s: %u %s ", + counter, + domains[counter % (sizeof(domains)/sizeof(char*))], + res, + ip.toString().c_str()); +#else // BLOCKING_DNS_RESOLUTION + state = 2; + auto res = CLwipIf::getInstance().getHostByName( + domains[counter % (sizeof(domains)/sizeof(char*))], + dns_cbk); + + if(res != 1) { + counter++; + } +#endif // BLOCKING_DNS_RESOLUTION + break; + } + case 2: + // do nothing, request made, wait for request to complete + break; + } + +} + From 9cb6f5529bcdca6d65a0dee28970b91ad9530d4d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 12 Jan 2024 10:44:01 +0100 Subject: [PATCH 58/79] enablig execution of network stack in interrrupt context] --- libraries/lwIpWrapper/src/CNetIf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index c113db86..20e97045 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -27,7 +27,7 @@ #include "lwIP_Arduino.h" #endif -// #define LWIP_USE_TIMER +#define LWIP_USE_TIMER #ifdef LWIP_USE_TIMER #include "FspTimer.h" From 99ca0fa8ce50de6b3793d52847cde198940045d3 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 17 Jan 2024 18:51:23 +0100 Subject: [PATCH 59/79] added disconnect and link status for retrocompatibility --- libraries/lwIpWrapper/src/CNetIf.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 20e97045..757d4812 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -79,6 +79,12 @@ typedef enum { NI_ETHERNET } NetIfType_t; +enum EthernetLinkStatus { + Unknown, + LinkON, + LinkOFF +}; + #define MAX_CLIENT MEMP_NUM_TCP_PCB #define MAX_DHCP_TRIES 4 #define TIMEOUT_DNS_REQUEST 10000U @@ -140,6 +146,10 @@ class CNetIf: public NetworkInterface { virtual void up(); virtual void down(); + inline int disconnect() { this->down(); return 0; } + + inline EthernetLinkStatus linkStatus() { return netif_is_link_up(&ni) ? LinkON : LinkOFF; } + bool isLinkUp() { return (bool)netif_is_link_up(&ni); } struct netif* getNi() { return ∋ } From 7e88a577e64119128aede33b897c273e26ef697a Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 19 Jan 2024 16:12:44 +0100 Subject: [PATCH 60/79] fixing lwip server --- libraries/Ethernet/src/EthernetClient.h | 3 +- libraries/Ethernet/src/EthernetServer.h | 3 +- libraries/WiFi/src/WiFiClient.h | 3 +- libraries/WiFi/src/WiFiServer.h | 3 +- libraries/lwIpWrapper/src/lwipClient.cpp | 35 +++++++++++---------- libraries/lwIpWrapper/src/lwipServer.cpp | 40 ++++++++++++++++++------ libraries/lwIpWrapper/src/lwipServer.h | 4 ++- 7 files changed, 61 insertions(+), 30 deletions(-) diff --git a/libraries/Ethernet/src/EthernetClient.h b/libraries/Ethernet/src/EthernetClient.h index 7e201c76..8d648b57 100644 --- a/libraries/Ethernet/src/EthernetClient.h +++ b/libraries/Ethernet/src/EthernetClient.h @@ -9,8 +9,9 @@ class EthernetClient : public lwipClient { EthernetClient(struct tcp_pcb *pcb, lwipServer *server) : lwipClient(pcb, server) { } - EthernetClient(lwipClient c) + EthernetClient(const lwipClient &c) : lwipClient(c) { + this->bindCNetIf(Ethernet); } int connect(IPAddress ip, uint16_t port) { diff --git a/libraries/Ethernet/src/EthernetServer.h b/libraries/Ethernet/src/EthernetServer.h index 1dbf791d..bb48d426 100644 --- a/libraries/Ethernet/src/EthernetServer.h +++ b/libraries/Ethernet/src/EthernetServer.h @@ -12,6 +12,7 @@ class EthernetServer: public lwipServer { } EthernetClient available() { - return EthernetClient(lwipServer::available()); + lwipClient* res = available_ptr(); + return res != nullptr ? EthernetClient(*res) : EthernetClient(CLIENT_NONE); } }; diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index 29d229ee..cad993d3 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -9,8 +9,9 @@ class WiFiClient: public lwipClient { WiFiClient(struct tcp_pcb *pcb, lwipServer *server) : lwipClient(pcb, server) { } - WiFiClient(lwipClient c) + WiFiClient(const lwipClient &c) : lwipClient(c) { + this->bindCNetIf(WiFiStation); } int connect(IPAddress ip, uint16_t port) { diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index c6d6a35f..f06d8f77 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -12,6 +12,7 @@ class WiFiServer: public lwipServer { } WiFiClient available() { - return WiFiClient(lwipServer::available()); + lwipClient* res = available_ptr(); + return res != nullptr ? WiFiClient(*res) : WiFiClient(CLIENT_NONE); } }; diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 8dfc454c..1147a956 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -80,7 +80,9 @@ lwipClient& lwipClient::operator=(lwipClient&& rhs) { } lwipClient::~lwipClient() { - this->stop(); + if(this->tcp_info->state != TCP_CLOSING) { + this->stop(); + } } int lwipClient::connect(const char* host, uint16_t port) { @@ -231,7 +233,7 @@ err_t lwipClient::recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err) return ERR_OK; } arduino::lock(); - if(this->tcp_info->state == TCP_CONNECTED) { + if(this->tcp_info->state == TCP_CONNECTED || this->tcp_info->state == TCP_ACCEPTED) { if (this->tcp_info->pbuf_head == nullptr) { // no need to increment the references of the pbuf, // since it is already 1 and lwip shifts the control to this code @@ -273,16 +275,11 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { } else if(res == ERR_MEM) { // FIXME handle this: we get into this case only if the sent data cannot be put in the send queue } - - // TODO understand if the tcp_write will send data if the buffer is not full - // force send only if we filled the send buffer - // if (ERR_OK != tcp_output(this->tcp_info->pcb)) { - // // return 0; - // break; - // } } while(buffer_cursor < buffer + size); - arduino::unlock(); + tcp_output(this->tcp_info->pcb); + + arduino::unlock(); return buffer - buffer_cursor; } @@ -342,13 +339,13 @@ void lwipClient::flush() { } void lwipClient::stop() { - tcp_recv(this->tcp_info->pcb, nullptr); - tcp_sent(this->tcp_info->pcb, nullptr); - tcp_poll(this->tcp_info->pcb, nullptr, 0); - tcp_err(this->tcp_info->pcb, nullptr); - tcp_accept(this->tcp_info->pcb, nullptr); - if(this->tcp_info->pcb != nullptr) { + tcp_recv(this->tcp_info->pcb, nullptr); + tcp_sent(this->tcp_info->pcb, nullptr); + tcp_poll(this->tcp_info->pcb, nullptr, 0); + tcp_err(this->tcp_info->pcb, nullptr); + tcp_accept(this->tcp_info->pcb, nullptr); + err_t err = tcp_close(this->tcp_info->pcb); this->tcp_info->state = TCP_CLOSING; @@ -362,6 +359,12 @@ void lwipClient::stop() { // if(tcp->p != nullptr) { // pbuf_free(tcp->p); // FIXME it happens that a pbuf, with ref == 0 is added for some reason // } + if(this->tcp_info->server != nullptr) { + // need to first make the server point to nullptr, then remove the client, can cause infinite recursion + auto server = this->tcp_info->server; + this->tcp_info->server = nullptr; + server->remove(this); + } } uint8_t lwipClient::connected() { diff --git a/libraries/lwIpWrapper/src/lwipServer.cpp b/libraries/lwIpWrapper/src/lwipServer.cpp index 151b1f9d..360c33fa 100644 --- a/libraries/lwIpWrapper/src/lwipServer.cpp +++ b/libraries/lwIpWrapper/src/lwipServer.cpp @@ -5,6 +5,7 @@ extern "C" { #include "CNetIf.h" #include "lwipClient.h" #include "lwipServer.h" +#include "utils.h" err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err); @@ -74,9 +75,12 @@ void lwipServer::begin(uint16_t port) // } void lwipServer::remove(lwipClient* client) { + arduino::lock(); + bool found = false; for (int i=0; i < size; i++) { if(found) { + // we move the client to delete to the end of the array, then we remove it clients[i-1] = clients[i]; } else if(*client == *clients[i]) { found = true; @@ -85,25 +89,41 @@ void lwipServer::remove(lwipClient* client) { delete clients[--size]; clients[size] = nullptr; + + arduino::unlock(); } -void lwipServer::accept(struct tcp_pcb* new_client) { +bool lwipServer::accept(struct tcp_pcb* new_client) { + bool res = false; // this->clean(); - + arduino::lock(); if(size < MAX_CLIENT-1) { clients[size] = new lwipClient(new_client, this); size++; clients_available++; + res = true; } + arduino::unlock(); + + return res; } lwipClient lwipServer::available() { + lwipClient* res = available_ptr(); + return res != nullptr ? *res : CLIENT_NONE; +} + +lwipClient* lwipServer::available_ptr() +{ + lwipClient* res=nullptr; + arduino::lock(); if(size > 0 && clients_available>0) { - return *clients[size-clients_available--]; // TODO verify index - } else { - return CLIENT_NONE; + res = clients[size-clients_available--]; // TODO verify index } + arduino::unlock(); + + return res; } size_t lwipServer::write(uint8_t b) @@ -112,28 +132,30 @@ size_t lwipServer::write(uint8_t b) } size_t lwipServer::write(const uint8_t* buffer, size_t size) { + arduino::lock(); size_t written=0; // this->clean(); for (int i = 0; i < MAX_CLIENT; i++) { written += clients[i]->write(buffer, size); } + arduino::unlock(); return written; } err_t tcp_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err) { + arduino::lock(); lwipServer* server = (lwipServer*) arg; - err_t ret_err; + err_t ret_err = ERR_OK; /* set priority for the newly accepted tcp connection newpcb */ tcp_setprio(newpcb, TCP_PRIO_MIN); - if ((arg != NULL) && (ERR_OK == err)) { - server->accept(newpcb); - } else { + if ((arg == NULL) || (ERR_OK != err) || !server->accept(newpcb)) { tcp_close(newpcb); ret_err = ERR_ARG; } + arduino::unlock(); return ret_err; } \ No newline at end of file diff --git a/libraries/lwIpWrapper/src/lwipServer.h b/libraries/lwIpWrapper/src/lwipServer.h index c08514ad..2a744692 100644 --- a/libraries/lwIpWrapper/src/lwipServer.h +++ b/libraries/lwIpWrapper/src/lwipServer.h @@ -31,10 +31,12 @@ class lwipServer: public Server { * - when a client connection is closed (by calling stop on it or delete on the client) * the server is notified and the remove() method is called thus the client is removed from the server list. */ - void accept(struct tcp_pcb* new_client); + bool accept(struct tcp_pcb* new_client); // void clean(); void remove(lwipClient* client); + lwipClient* available_ptr(); + uint16_t _port; const IPAddress &listen_address; tcp_pcb* server_pcb; From 88f50911c3ba1bc93a1285e872fcb1236c014f76 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 19 Jan 2024 16:40:29 +0100 Subject: [PATCH 61/79] blocking begin call on dhcp acquisition --- libraries/lwIpWrapper/src/CNetIf.cpp | 24 +++++++++++++++++------- libraries/lwIpWrapper/src/CNetIf.h | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 51cc1550..842caa98 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -316,18 +316,28 @@ int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) netif_set_up(&this->ni); + // add the interface to the network stack + CLwipIf::getInstance().add_iface(this); // TODO remove interface when it is needed (??) + netif_set_link_up(&this->ni); + #ifdef LWIP_DHCP // dhcp is started when begin gets ip == nullptr if(ip != INADDR_NONE) { this->dhcpNotUsed(); } else { this->dhcpStart(); + + + CLwipIf::getInstance().sync_timer(); + while(!this->isDhcpAcquired()) { + CLwipIf::getInstance().task(); + } + CLwipIf::getInstance().enable_timer(); } + #endif - // add the interface to the network stack - CLwipIf::getInstance().add_iface(this); // TODO remove interface when it is needed (??) - return 0; + return this->isDhcpAcquired()? 1 : 0; } void CNetIf::task() { @@ -452,12 +462,12 @@ int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw, c this, std::placeholders:: _1, std::placeholders::_2)); // Call the begin function on the Parent class to init the interface - CNetIf::begin(ip, nm, gw); - netif_set_link_up(&this->ni); + // netif_set_link_up(&this->ni); + auto res = CNetIf::begin(ip, nm, gw); CLwipIf::getInstance().addDnsServer(dns); - return 0; + return res; } err_t CEth::init(struct netif* ni) { @@ -578,7 +588,7 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres res = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); CLwipIf::getInstance().enable_timer(); - CNetIf::begin(ip, nm, gw); + return CNetIf::begin(ip, nm, gw); exit: return res; } diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 757d4812..c9c95d02 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -180,7 +180,7 @@ class CNetIf: public NetworkInterface { struct netif ni; #ifdef LWIP_DHCP - bool dhcp_acquired; + volatile bool dhcp_acquired; #endif /* From 0f430c51c0fa18ac43c82681167695cb2be731aa Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 22 Jan 2024 14:13:23 +0100 Subject: [PATCH 62/79] Making it possible to call multiple time the begin function on an interfare --- libraries/lwIpWrapper/src/CNetIf.cpp | 83 ++++++++++++++++++++-------- libraries/lwIpWrapper/src/CNetIf.h | 9 +-- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 842caa98..e8398793 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -302,18 +302,32 @@ int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) ip_addr_t _nm = fromArduinoIP(nm); ip_addr_t _gw = fromArduinoIP(gw); - // netif add copies the ip addresses into the netif, no need to store them also in the object - struct netif *_ni = netif_add( - &this->ni, - &_ip, &_nm, &_gw, // ip addresses are being copied and not taken as reference, use a local defined variable - this, - _netif_init, - ethernet_input - ); - if(_ni == nullptr) { - return -1; - } + char name[3] = { + ni.name[0], + ni.name[1], + ni.num + '0', + }; + if(netif_find(name) == nullptr) { + + // netif add copies the ip addresses into the netif, no need to store them also in the object + struct netif *_ni = netif_add( + &this->ni, + &_ip, &_nm, &_gw, // ip addresses are being copied and not taken as reference, use a local defined variable + this, + _netif_init, + ethernet_input + ); + + if(_ni == nullptr) { + return -1; + } + } else { + if (netif_is_link_up(&this->ni)) { + netif_set_down(&this->ni); + } + // TODO check for any changes detected and update the iface + } netif_set_up(&this->ni); // add the interface to the network stack @@ -448,7 +462,7 @@ bool CNetIf::dhcpRenew() { /* ########################################################################## * ETHERNET NETWORK INTERFACE CLASS * ########################################################################## */ -uint8_t CEth::eth_id = 0; +const char CEth::eth_ifname[] = "en"; CEth::CEth(NetworkDriver *driver) : CNetIf(driver) { @@ -470,19 +484,42 @@ int CEth::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw, c return res; } +int CEth::begin( + uint8_t *mac_address, + const IPAddress &local_ip, + const IPAddress &dns_server, + const IPAddress &gateway, + const IPAddress &subnet, + const unsigned long timeout, + const unsigned long responseTimeout) { + + this->setMacAddress(mac_address); + + return this->begin(local_ip, subnet, gateway, dns_server); +} + +int CEth::begin( + uint8_t *mac_address, + const unsigned long timeout, + const unsigned long responseTimeout) { + + this->setMacAddress(mac_address); + + return this->begin(); +} + + err_t CEth::init(struct netif* ni) { // Setting up netif #if LWIP_NETIF_HOSTNAME ni->hostname = "C33_eth"; #endif - ni->name[0] = CEth::eth_ifname_prefix; - ni->name[1] = '0' + CEth::eth_id++; + ni->name[0] = CEth::eth_ifname[0]; + ni->name[1] = CEth::eth_ifname[1]; ni->mtu = 1500; // TODO get this from the network ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; memcpy(ni->hwaddr, this->driver->getMacAddress(), 6); // FIXME handle this using a constant - // ni->hwaddr = C33EthernetDriver.getMacAddress(); - // ni->hwaddr_len = sizeof(macaddress); ni->hwaddr_len = 6; ni->output = etharp_output; @@ -549,7 +586,7 @@ void CEth::consume_callback(uint8_t* buffer, uint32_t len) { /* ########################################################################## */ /* CWifiStation NETWORK INTERFACE CLASS */ /* ########################################################################## */ -uint8_t CWifiStation::wifistation_id = 0; +const char CWifiStation::wifistation_ifname[] = "ws"; CWifiStation::CWifiStation() : hw_init(false) { @@ -673,8 +710,8 @@ err_t CWifiStation::init(struct netif* ni) { #if LWIP_NETIF_HOSTNAME ni->hostname = "C33-WifiSta"; #endif - ni->name[0] = CWifiStation::wifistation_ifname_prefix; - ni->name[1] = '0' + CWifiStation::wifistation_id++; + ni->name[0] = CWifiStation::wifistation_ifname[0]; + ni->name[1] = CWifiStation::wifistation_ifname[1]; ni->mtu = 1500; // FIXME get this from the network ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; @@ -859,7 +896,7 @@ int CWifiStation::resetLowPowerMode() { /* ########################################################################## */ /* CWifiSoftAp NETWORK INTERFACE CLASS */ /* ########################################################################## */ -uint8_t CWifiSoftAp::softap_id = 0; +const char CWifiSoftAp::softap_ifname[] = "sa"; // This is required for dhcp server to assign ip addresses to AP clients IPAddress default_nm("255.255.255.0"); @@ -883,7 +920,7 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress return ESP_CONTROL_OK; }); - if ((res=CEspControl::getInstance().initSpiDriver()) != 0) { + if ((res=CEspControl::getInstance().initSpiDriver()) != 0 && !hw_init) { // res = -1; // FIXME put a proper error code goto exit; } @@ -953,8 +990,8 @@ err_t CWifiSoftAp::init(struct netif* ni) { // TODO pass the hostname in the constructor os with a setter ni->hostname = "C33-SoftAP"; #endif - ni->name[0] = CWifiSoftAp::softap_ifname_prefix; - ni->name[1] = '0' + CWifiSoftAp::softap_id++; + ni->name[0] = CWifiSoftAp::softap_ifname[0]; + ni->name[1] = CWifiSoftAp::softap_ifname[1]; ni->mtu = 1500; // FIXME get this from the network ni->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index c9c95d02..0c639327 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -234,8 +234,7 @@ class CEth : public CNetIf { */ err_t output(struct netif* ni, struct pbuf* p) override; - static const char eth_ifname_prefix = 'e'; - static uint8_t eth_id; + static const char eth_ifname[]; private: /* * This function is passed to the driver class and it is meant to @@ -278,8 +277,7 @@ class CWifiStation : public CNetIf { int setLowPowerMode(); int resetLowPowerMode(); protected: - static const char wifistation_ifname_prefix = 'w'; - static uint8_t wifistation_id; + static const char wifistation_ifname[]; /* * this function is used to initialize the netif structure of lwip @@ -322,8 +320,7 @@ class CWifiSoftAp : public CNetIf { int setLowPowerMode(); int resetLowPowerMode(); protected: - static const char softap_ifname_prefix = 's'; - static uint8_t softap_id; + static const char softap_ifname[]; /* * this function is used to initialize the netif structure of lwip */ From ec3cba55e47302e6b07fce224f91411a2c253658 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 22 Jan 2024 14:19:07 +0100 Subject: [PATCH 63/79] making netif compatible with connection handler usage --- libraries/WiFi/src/WiFi.cpp | 9 +++-- libraries/lwIpWrapper/src/CNetIf.cpp | 39 +++++++++--------- libraries/lwIpWrapper/src/CNetIf.h | 59 +++++++++++++++++++++++----- 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index bfe4906d..a6154baa 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -23,16 +23,16 @@ const char* CWifi::firmwareVersion() { /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid) { /* -------------------------------------------------------------------------- */ - WiFiStation.begin(); - return WiFiStation.connectToAP(ssid, nullptr); + WiFiStation.connectToAP(ssid, nullptr); + return WiFiStation.begin(); } /* -------------------------------------------------------------------------- */ int CWifi::begin(const char* ssid, const char *passphrase) { /* -------------------------------------------------------------------------- */ - WiFiStation.begin(); - return WiFiStation.connectToAP(ssid, passphrase); + WiFiStation.connectToAP(ssid, passphrase); + return WiFiStation.begin();; } /* passphrase is needed so a default one will be set */ @@ -242,6 +242,7 @@ uint8_t CWifi::channel(uint8_t networkItem) { uint8_t CWifi::status() { // FIXME /* -------------------------------------------------------------------------- */ // return CLwipIf::getInstance().getWifiStatus(); + return WiFiStation.status(); } /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index e8398793..1b33457c 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -597,11 +597,19 @@ CWifiStation::~CWifiStation() { } int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) { - int res = 0; + return CNetIf::begin(ip, nm, gw); +} + +int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { + WifiApCfg_t ap; + int rv = ESP_CONTROL_CTRL_ERROR; // FIXME this should be set with an error meaning AP not found + bool found = false; + int8_t best_index = -1; // this index is used to find the ap with the best rssi int time_num = 0; CEspControl::getInstance().listenForStationDisconnectEvent([this] (CCtrlMsgWrapper *resp) -> int { netif_set_link_down(&this->ni); + wifi_status = WL_DISCONNECTED; return ESP_CONTROL_OK; }); CEspControl::getInstance().listenForInitEvent([this] (CCtrlMsgWrapper *resp) -> int { @@ -610,10 +618,11 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres return ESP_CONTROL_OK; }); - if ((res=CEspControl::getInstance().initSpiDriver()) != 0) { - res = -1; // FIXME put a proper error code + if ((rv=CEspControl::getInstance().initSpiDriver()) != 0 && !hw_init) { + rv = -1; // FIXME put a proper error code goto exit; } + wifi_status = WL_NO_SSID_AVAIL; while (time_num < 100 && !hw_init) { // TODO #define WIFI_INIT_TIMEOUT_MS 10000 CEspControl::getInstance().communicateWithEsp(); @@ -622,21 +631,11 @@ int CWifiStation::begin(const IPAddress &ip, const IPAddress &nm, const IPAddres } CLwipIf::getInstance().sync_timer(); - res = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); + rv = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); CLwipIf::getInstance().enable_timer(); - return CNetIf::begin(ip, nm, gw); -exit: - return res; -} - -int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { - WifiApCfg_t ap; - int rv = ESP_CONTROL_CTRL_ERROR; // FIXME this should be set with an error meaning AP not found - bool found = false; - int8_t best_index = -1; // this index is used to find the ap with the best rssi - if((rv=this->scanForAp()) != WL_SCAN_COMPLETED) { + rv = -2; goto exit; } @@ -666,8 +665,12 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { if (rv == ESP_CONTROL_OK) { CEspControl::getInstance().getAccessPointConfig(access_point_cfg); + wifi_status = WL_CONNECTED; + netif_set_link_up(&this->ni); + } else { + wifi_status = WL_CONNECT_FAILED; } CLwipIf::getInstance().enable_timer(); } @@ -685,13 +688,13 @@ int CWifiStation::scanForAp() { CLwipIf::getInstance().enable_timer(); if (res == ESP_CONTROL_OK) { - res = WL_SCAN_COMPLETED; + wifi_status = WL_SCAN_COMPLETED; } else { - res = WL_NO_SSID_AVAIL; + wifi_status = WL_NO_SSID_AVAIL; } - return res; + return wifi_status; } // disconnect diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 0c639327..fc7bf876 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -79,12 +79,17 @@ typedef enum { NI_ETHERNET } NetIfType_t; -enum EthernetLinkStatus { +enum LinkStatus { Unknown, LinkON, LinkOFF }; +enum EthernetHardwareStatus { + EthernetNoHardware, + EthernetLwip = 7 +}; + #define MAX_CLIENT MEMP_NUM_TCP_PCB #define MAX_DHCP_TRIES 4 #define TIMEOUT_DNS_REQUEST 10000U @@ -148,7 +153,7 @@ class CNetIf: public NetworkInterface { inline int disconnect() { this->down(); return 0; } - inline EthernetLinkStatus linkStatus() { return netif_is_link_up(&ni) ? LinkON : LinkOFF; } + inline LinkStatus linkStatus() { return netif_is_link_up(&ni) ? LinkON : LinkOFF; } bool isLinkUp() { return (bool)netif_is_link_up(&ni); } @@ -164,16 +169,10 @@ class CNetIf: public NetworkInterface { IPAddress gatewayIP() { return IPAddress(this->getGwAdd()); } IPAddress dnsServerIP() { /* FIXME understand where dns should be managed */} - // FIXME hostname should be defined in the NetworkStack singleton - // void setHostname(const char* name) - // { - // memset(hostname, 0x00, MAX_HOSTNAME_DIM); - // memcpy(hostname, name, strlen(name) < MAX_HOSTNAME_DIM ? strlen(name) : MAX_HOSTNAME_DIM); - // } void config(IPAddress _ip, IPAddress _gw, IPAddress _nm); - virtual int getMacAddress(uint8_t* mac) = 0; + virtual int setMacAddress(uint8_t* mac) = 0; friend CLwipIf; protected: @@ -216,13 +215,40 @@ class CEth : public CNetIf { const IPAddress &gw = INADDR_NONE, const IPAddress &dns = INADDR_NONE); + // The following are overloaded begin methods kept for retrocompatibility with other Arduino cores + // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + virtual int begin( + uint8_t *mac_address, + const IPAddress &local_ip = INADDR_NONE, + const IPAddress &dns_server = INADDR_NONE, + const IPAddress &gateway = INADDR_NONE, + const IPAddress &subnet = INADDR_NONE, + const unsigned long timeout = 60000, + const unsigned long responseTimeout = 4000); + + virtual int begin( + uint8_t *mac_address, + const unsigned long timeout = 60000, + const unsigned long responseTimeout = 4000); + + virtual int getMacAddress(uint8_t* mac) override { UNUSED(mac); // FIXME not implemented return 1; } + virtual int setMacAddress(uint8_t* mac) override { + UNUSED(mac); // FIXME not implemented + return 1; + } + + int maintain() {} // Deprecated method for retrocompatibility void schedule(void) {} // Deprecated method for retrocompatibility + + inline EthernetHardwareStatus hardwareStatus() { return EthernetLwip; } protected: /* * this function is used to initialize the netif structure of lwip @@ -262,6 +288,11 @@ class CWifiStation : public CNetIf { // FIXME not implemented } + virtual int setMacAddress(uint8_t* mac) override { + UNUSED(mac); // FIXME not implemented + return 1; + } + virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); virtual int32_t getRSSI(); @@ -276,6 +307,10 @@ class CWifiStation : public CNetIf { int setLowPowerMode(); int resetLowPowerMode(); + + inline WifiStatus_t status() { + return wifi_status; + } protected: static const char wifistation_ifname[]; @@ -293,6 +328,7 @@ class CWifiStation : public CNetIf { std::vector access_points; WifiApCfg_t access_point_cfg; bool hw_init; // TODO this should be moved to the wifi driver class + WifiStatus_t wifi_status = WL_IDLE_STATUS; // TODO this should be moved to the wifi driver class }; class CWifiSoftAp : public CNetIf { @@ -312,6 +348,11 @@ class CWifiSoftAp : public CNetIf { // FIXME not implemented } + virtual int setMacAddress(uint8_t* mac) override { + UNUSED(mac); // FIXME not implemented + return 1; + } + virtual const char* getSSID(); virtual uint8_t* getBSSID(uint8_t* bssid); virtual uint8_t getEncryptionType(); From e56d9f9ae001ac31f74c934f6a6baed499f5123d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 23 Jan 2024 15:14:33 +0100 Subject: [PATCH 64/79] fixing return status of begin --- libraries/WiFi/src/WiFi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index a6154baa..99de072c 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -32,7 +32,8 @@ int CWifi::begin(const char* ssid) { int CWifi::begin(const char* ssid, const char *passphrase) { /* -------------------------------------------------------------------------- */ WiFiStation.connectToAP(ssid, passphrase); - return WiFiStation.begin();; + WiFiStation.begin(); + return WiFiStation.status(); } /* passphrase is needed so a default one will be set */ From 1ac341d8b781706d4075bccf323c0d4da323db1c Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 23 Jan 2024 14:51:20 +0100 Subject: [PATCH 65/79] adding test files for lwipwrapper WIP --- .../ethernet_bare_lwipc33.ino | 551 +++++++++++++++++ .../examples/mixed_lwipc33/arduino_secrets.h | 2 + .../examples/mixed_lwipc33/mixed_lwipc33.ino | 565 ++++++++++++++++++ .../softap_bare_lwipc33.ino | 108 ++++ .../wifi_bare_lwipc33/arduino_secrets.h | 2 + .../wifi_bare_lwipc33/wifi_bare_lwipc33.ino | 547 +++++++++++++++++ 6 files changed, 1775 insertions(+) create mode 100644 libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino create mode 100644 libraries/lwIpWrapper/examples/mixed_lwipc33/arduino_secrets.h create mode 100644 libraries/lwIpWrapper/examples/mixed_lwipc33/mixed_lwipc33.ino create mode 100644 libraries/lwIpWrapper/examples/softap_bare_lwipc33/softap_bare_lwipc33.ino create mode 100644 libraries/lwIpWrapper/examples/wifi_bare_lwipc33/arduino_secrets.h create mode 100644 libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino diff --git a/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino new file mode 100644 index 00000000..521983ce --- /dev/null +++ b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino @@ -0,0 +1,551 @@ +#include +#include +#include +#include +#include + +// #define CNETIF_STATS_ENABLED +// #include "CNetifStats.h" + +#ifdef CNETIF_STATS_ENABLED +#define STATS_BUFFER_SIZE 1000 +char cnetif_stats_buffer[STATS_BUFFER_SIZE]; +// netif_stats _stats; +#endif // CNETIF_STATS_ENABLED + +#include +#include + +#define CHECK_PAYLOAD + +/* --------------------------------------- */ +void timer_cb(timer_callback_args_t *arg); +void application(); +void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks=4, uint8_t cols=16); +void dump_buffer_char(uint8_t* b, uint32_t len); +void application_report(bool force=false); +bool verify_buffer_sequential_faster_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print= false); +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print=false); +void application_final_report(); +uint64_t debug_start; +/* --------------------------------------- */ + +void setup() { + Serial.begin(115200); + while(!Serial); + + Serial.println("Renesas file download example"); + + DEBUG_INFO("Setting up netif"); + // Ethernet.begin(&ip, &nm, &gw); + Ethernet.begin(); + + DEBUG_INFO("Begin of reception\n\n"); + debug_start = millis(); +} + +uint32_t counter=0; +void loop() { + // __disable_irq(); + uint32_t start = micros(); +#ifndef LWIP_USE_TIMER + CLwipIf::getInstance().task(); +#endif + // Handle application FSM + application(); + + if(millis() - debug_start > 3000) { // print the debug _stats every x second + // DEBUG_INFO("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + DEBUG_INFO("time: %12ums", millis()); + // DEBUG_INFO("memory: %12u bytes \tmin: %12u bytes \tmax: %12u bytes", + // memory_used, memory_used_min, memory_used_max); + DEBUG_INFO("loop counter %u\n", counter); + application_report(); + +#ifdef CNETIF_STATS_ENABLED + netif_stats_sprintf(cnetif_stats_buffer, Ethernet.stats, STATS_BUFFER_SIZE, (8*1e6)/(1<<20), "Mbit/s"); + // __disable_irq(); + arduino::lock(); + NETIF_STATS_RESET_AVERAGES(Ethernet.stats); + // __enable_irq(); + arduino::unlock(); + + DEBUG_INFO(cnetif_stats_buffer); +#endif // CNETIF_STATS_ENABLED + // DEBUG_INFO("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + + counter = 0; + // reset some counters + debug_start = millis(); + } + counter++; +} + +// Application level Stuff +enum app_state_t: uint8_t { + APP_STATE_NONE = 0, + APP_STATE_LINK_UP, + APP_STATE_LINK_DOWN, + APP_STATE_IFACE_UP, + APP_STATE_CONNECTING, + APP_STATE_CONNECTED, + APP_STATE_PARSE_HEADER, + APP_STATE_DOWNLOAD, + APP_STATE_DOWNLOAD_FAILED, + APP_STATE_DOWNLOAD_FINISHED, + APP_STATE_ERROR, + APP_STATE_RESET +}; + +static const char* state_strings[] = { + "APP_STATE_NONE", + "APP_STATE_LINK_UP", + "APP_STATE_LINK_DOWN", + "APP_STATE_IFACE_UP", + "APP_STATE_CONNECTING", + "APP_STATE_CONNECTED", + "APP_STATE_PARSE_HEADER", + "APP_STATE_DOWNLOAD", + "APP_STATE_DOWNLOAD_FAILED", + "APP_STATE_DOWNLOAD_FINISHED", + "APP_STATE_ERROR", + "APP_STATE_RESET" +}; + +#define APP_BUFFER_SIZE 1*1024 + + +struct App { + app_state_t current_state=APP_STATE_NONE; + app_state_t prev_state=APP_STATE_NONE; + + lwipClient *tcp_client; + uint16_t port = 8000; + IPAddress server_ip = IPAddress(192, 168, 10, 250); + + uint8_t buffer[APP_BUFFER_SIZE]; + + size_t file_length=0; + size_t downloaded_bytes=0; + std::string http_header; + + // stats related variables + uint32_t start = 0; + uint32_t speed_start = 0; + uint32_t speed_bytes = 0; + + // payload verification parameters + uint32_t payload_verify_offset=0; + uint8_t payload_verify_excess[4]={}; // this should be 3, but there are bugs + uint8_t payload_verify_excess_len=0; + uint32_t last_value=0; +} app; + +void init_app(struct App& app) { + app.file_length = 0; + app.http_header = ""; + app.downloaded_bytes = 0; + app.start = 0; + app.payload_verify_excess_len = 0; + app.payload_verify_offset = 0; + app.last_value=0; + app.speed_bytes = 0; +} + +void reset_app(struct App& app) { + init_app(app); + + if(app.tcp_client != nullptr) { + app.tcp_client->stop(); + // delete app.tcp_client; + } +} + +const char* http_request = "GET /test-4M HTTP/1.1\nHost: 192.168.10.250\nConnection: close\n\n"; + +void application() { + bool found = false; + uint16_t bytes_read=0; + + switch(app.current_state) { + case APP_STATE_NONE: + init_app(app); + + // TODO we are not handling link connection and disconnection + app.prev_state = app.current_state; + app.current_state = APP_STATE_LINK_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_LINK_UP: + if(Ethernet.isDhcpAcquired()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + break; + case APP_STATE_IFACE_UP: + // The link is up we connect to the server + app.tcp_client = new lwipClient; + + // Connection details: + app.tcp_client->connect(app.server_ip, app.port); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTING; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_CONNECTING: + // do nothing, until the TCP connection is established + // TODO handle timeout for connection and go to error state + if(app.tcp_client->connected()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + + break; + + case APP_STATE_CONNECTED: + app.tcp_client->write((uint8_t*)http_request, strlen(http_request)); + app.start = millis(); + app.speed_start = app.start; + + app.prev_state = app.current_state; + app.current_state = APP_STATE_PARSE_HEADER; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_PARSE_HEADER: + // FIXME + bytes_read = app.tcp_client->read_until_token(app.buffer, APP_BUFFER_SIZE, "\r\n\r\n", found); + // DEBUG_INFO("%s", app.http_header.c_str()); + + if(bytes_read>0) { + // put the buffer into an http header string + std::string chunk((char*)app.buffer, bytes_read); + app.http_header += chunk; + app.speed_bytes += bytes_read; + DEBUG_INFO("%s", app.http_header.c_str()); + } + + if(found) { // FIXME reduce indentation level + // we found the http terminating token, go to the next app phase if we extracted the file len + // otherwise go in error phase + + // Parse the http header and gather information needed for the download + // dump_buffer_char(app.buffer, APP_BUFFER_SIZE); + + std::regex content_length_regex("Content-Length: ([0-9]+)", std::regex::icase); + std::smatch matches; + + // DEBUG_INFO(app.http_header.c_str()); + + if(std::regex_search(app.http_header, matches, content_length_regex)) { + app.file_length = stoi(matches[1].str()); + + DEBUG_INFO("Download started, file length: %u", app.file_length); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } else { + // Failed to extract the content length from the header, going into an error state + // TODO report the reason of the error + + app.prev_state = app.current_state; + app.current_state = APP_STATE_ERROR; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + } + break; + case APP_STATE_DOWNLOAD: + if(app.tcp_client->available() <= 0) { // no data available + break; + } + + bytes_read = app.tcp_client->read(app.buffer, APP_BUFFER_SIZE); + // DEBUG_INFO("read %6u, available %6u", bytes_read, app.tcp_client->available()); + + if(bytes_read > 0) { + app.downloaded_bytes += bytes_read; + app.speed_bytes += bytes_read; + + // dump_buffer(app.buffer, APP_BUFFER_SIZE, 4, 128); +#ifdef CHECK_PAYLOAD + // if(!verify_buffer_sequential_4B( + if(!verify_buffer_sequential_faster_4B( + app.buffer, + bytes_read, + app.payload_verify_offset, + app.payload_verify_excess, + app.payload_verify_excess_len, + false)) { + + DEBUG_INFO("Payload verification failed"); + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FAILED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } +#endif // CHECK_PAYLOAD + } + + // test for faking download failed + // if(app.downloaded_bytes > app.file_length/6) { + // app.prev_state = app.current_state; + // app.current_state = APP_STATE_DOWNLOAD_FAILED; + // } + + if(app.downloaded_bytes == app.file_length) { + app.last_value = + *(app.buffer + bytes_read - 4) << 24 | + *(app.buffer + bytes_read - 3) << 16 | + *(app.buffer + bytes_read - 2) << 8 | + *(app.buffer + bytes_read - 1); + + // if the download of the counter file is correct the last value should be + // the size of the file/4 -1 + if(app.last_value == (app.downloaded_bytes/4 - 1)) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FINISHED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } else { + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FAILED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + } + break; + + case APP_STATE_DOWNLOAD_FAILED: + // TODO report error in file download and close the connection + app.prev_state = app.current_state; + app.current_state = APP_STATE_ERROR; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_DOWNLOAD_FINISHED: + DEBUG_INFO("Download finished: %uMB", app.downloaded_bytes>>20); + DEBUG_INFO("Last value in the buffer: 0x%08X", app.last_value); + application_final_report(); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_RESET; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_ERROR: + // The app reached an expected error state + // TODO report this state and go in the default, status not defined handler to reset the state + case APP_STATE_RESET: + // in this state we reset the application and we start back from the beginning + + reset_app(app); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + } +} + +// application stats +void application_report(bool force) { + if(force || app.current_state == APP_STATE_PARSE_HEADER || app.current_state == APP_STATE_DOWNLOAD) { + + // float speed_conversion_factor = 1e3/(1<<10); + float speed_conversion_factor = 8*1e3/float(1<<20); + float elapsed = millis()-app.speed_start; + + float speed = (app.speed_bytes / elapsed) * speed_conversion_factor; + DEBUG_INFO("Application layer: %12u/%12u speed: %.2f Mbit/s", app.downloaded_bytes, app.file_length, speed); + + app.speed_start = millis(); + app.speed_bytes = 0; + } +} + +void application_final_report() { + // float speed_conversion_factor = 10e3/(1<<10); + float speed_conversion_factor = 1e3*8/float(1<<20); + + float elapsed = millis()-app.start; + float speed = (app.downloaded_bytes / elapsed) * speed_conversion_factor; + DEBUG_INFO( + "Application layer: Downloaded %u MB in %.2fs average speed: %.2f Mbit/s", + app.downloaded_bytes>>20, elapsed/1000, speed); +} + +// payload checking function +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print) { + size_t i=0; + bool res = true; + uint32_t value=0, first=0; + + if(excess_len > 0) { + uint8_t j=0; + for(; j 0) { + // the first value needs to be taken from the excess bytes of the previous buffer and the first of this + uint8_t j=0; + for(; j>>>>>>"); + for(uint8_t *p=b; p>>>>>>"); + for(uint8_t *p=b; p +#include +#include +#include +#include "arduino_secrets.h" +#include +#include + +// #define CNETIF_STATS_ENABLED +// #include "CNetifStats.h" + +#ifdef CNETIF_STATS_ENABLED +#define STATS_BUFFER_SIZE 1000 +char cnetif_stats_buffer[STATS_BUFFER_SIZE]; +// netif_stats _stats; +#endif // CNETIF_STATS_ENABLED + +static char const SSID[] = SECRET_SSID; /* your network SSID (name) */ +static char const PASS[] = SECRET_PASS; /* your network password (use for WPA, or use as key for WEP) */ + +// #define ETHER_CFG_PARAM_CHECKING_ENABLE +// Renesas libraries + +#define CHECK_PAYLOAD + +/* --------------------------------------- */ +void timer_cb(timer_callback_args_t *arg); +void application(); +void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks=4, uint8_t cols=16); +void dump_buffer_char(uint8_t* b, uint32_t len); +void application_report(bool force=false); +bool verify_buffer_sequential_faster_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print= false); +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print=false); +void application_final_report(); +uint64_t debug_start; +/* --------------------------------------- */ + +void setup() { + Serial.begin(115200); + while(!Serial); + + Serial.println("Renesas file download example"); + int res = 0; + + DEBUG_INFO("Setting up Eth netif"); + Ethernet.begin(); + + DEBUG_INFO("Connecting to AP"); + while((res=WiFi.begin(SSID, SECRET_PASS)) != ESP_CONTROL_OK) { + DEBUG_INFO("Connection failed retry: %d", res); + delay(1000); + } + DEBUG_INFO("Connected to AP"); + + DEBUG_INFO("Begin of reception\n\n"); + debug_start = millis(); +} + +uint32_t counter=0; +void loop() { + // __disable_irq(); + uint32_t start = micros(); +#ifndef LWIP_USE_TIMER + CLwipIf::getInstance().task(); +#endif + // Handle application FSM + application(); + + if(millis() - debug_start > 3000) { // print the debug _stats every x second + // DEBUG_INFO("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + DEBUG_INFO("time: %12ums", millis()); + // DEBUG_INFO("memory: %12u bytes \tmin: %12u bytes \tmax: %12u bytes", + // memory_used, memory_used_min, memory_used_max); + DEBUG_INFO("loop counter %u\n", counter); + application_report(); + + +#ifdef CNETIF_STATS_ENABLED + netif_stats_sprintf(cnetif_stats_buffer, WiFi.stats, STATS_BUFFER_SIZE, (8*1e6)/(1<<20), "Mbit/s"); + // __disable_irq(); + arduino::lock(); + NETIF_STATS_RESET_AVERAGES(WiFi.stats); + // __enable_irq(); + arduino::unlock(); + + DEBUG_INFO(cnetif_stats_buffer); +#endif // CNETIF_STATS_ENABLED + // DEBUG_INFO("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + + counter = 0; + // reset some counters + debug_start = millis(); + } + counter++; +} + +// Application level Stuff +enum app_state_t: uint8_t { + APP_STATE_NONE = 0, + APP_STATE_LINK_UP, + APP_STATE_LINK_DOWN, + APP_STATE_IFACE_UP, + APP_STATE_CONNECTING, + APP_STATE_CONNECTED, + APP_STATE_PARSE_HEADER, + APP_STATE_DOWNLOAD, + APP_STATE_DOWNLOAD_FAILED, + APP_STATE_DOWNLOAD_FINISHED, + APP_STATE_ERROR, + APP_STATE_RESET +}; + +static const char* state_strings[] = { + "APP_STATE_NONE", + "APP_STATE_LINK_UP", + "APP_STATE_LINK_DOWN", + "APP_STATE_IFACE_UP", + "APP_STATE_CONNECTING", + "APP_STATE_CONNECTED", + "APP_STATE_PARSE_HEADER", + "APP_STATE_DOWNLOAD", + "APP_STATE_DOWNLOAD_FAILED", + "APP_STATE_DOWNLOAD_FINISHED", + "APP_STATE_ERROR", + "APP_STATE_RESET" +}; + +#define APP_BUFFER_SIZE 1*1024 + + +struct App { + app_state_t current_state=APP_STATE_NONE; + app_state_t prev_state=APP_STATE_NONE; + + uint8_t clients_counter=0; + lwipClient *tcp_client; + uint16_t port = 8000; + IPAddress server_ip = IPAddress(192, 168, 10, 250); + + uint8_t buffer[APP_BUFFER_SIZE]; + + size_t file_length=0; + size_t downloaded_bytes=0; + std::string http_header; + + // stats related variables + uint32_t start = 0; + uint32_t speed_start = 0; + uint32_t speed_bytes = 0; + + // payload verification parameters + uint32_t payload_verify_offset=0; + uint8_t payload_verify_excess[4]={}; // this should be 3, but there are bugs + uint8_t payload_verify_excess_len=0; + uint32_t last_value=0; +} app; + +void init_app(struct App& app) { + app.file_length = 0; + app.http_header = ""; + app.downloaded_bytes = 0; + app.start = 0; + app.payload_verify_excess_len = 0; + app.payload_verify_offset = 0; + app.last_value=0; + app.speed_bytes = 0; +} + +void reset_app(struct App& app) { + init_app(app); + + if(app.tcp_client != nullptr) { + delete app.tcp_client; + } +} + +const char* http_request = "GET /test-1M HTTP/1.1\nHost: 192.168.10.250\nConnection: close\n\n"; + +void application() { + bool found = false; + uint16_t bytes_read=0; + + switch(app.current_state) { + case APP_STATE_NONE: + init_app(app); + + // TODO we are not handling link connection and disconnection + app.prev_state = app.current_state; + app.current_state = APP_STATE_LINK_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_LINK_UP: + if(WiFiStation.isDhcpAcquired() && Ethernet.isDhcpAcquired()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + break; + case APP_STATE_IFACE_UP: + // The link is up we connect to the server + // app.tcp_client = new lwipClient; + + if((app.clients_counter++) % 2 == 1) { + DEBUG_INFO("Download with Eth interface"); + app.tcp_client = new EthernetClient; + } else { + DEBUG_INFO("Download with WiFi interface"); + app.tcp_client = new WiFiClient; + } + // CLwipIf::getInstance().setDefaultIface((app.clients_counter++)%2==1? (CNetIf*)&Ethernet: (CNetIf*)&WiFiStation); + + + // Connection details: + app.tcp_client->connect(app.server_ip, app.port); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTING; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_CONNECTING: + // do nothing, until the TCP connection is established + // TODO handle timeout for connection and go to error state + if(app.tcp_client->connected()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + + break; + + case APP_STATE_CONNECTED: + app.tcp_client->write((uint8_t*)http_request, strlen(http_request)); + app.start = millis(); + app.speed_start = app.start; + + app.prev_state = app.current_state; + app.current_state = APP_STATE_PARSE_HEADER; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_PARSE_HEADER: + // FIXME + bytes_read = app.tcp_client->read_until_token(app.buffer, APP_BUFFER_SIZE, "\r\n\r\n", found); + // DEBUG_INFO("%s", app.http_header.c_str()); + + if(bytes_read>0) { + // put the buffer into an http header string + std::string chunk((char*)app.buffer, bytes_read); + app.http_header += chunk; + app.speed_bytes += bytes_read; + DEBUG_INFO("%s", app.http_header.c_str()); + } + + if(found) { // FIXME reduce indentation level + // we found the http terminating token, go to the next app phase if we extracted the file len + // otherwise go in error phase + + // Parse the http header and gather information needed for the download + // dump_buffer_char(app.buffer, APP_BUFFER_SIZE); + + std::regex content_length_regex("Content-Length: ([0-9]+)", std::regex::icase); + std::smatch matches; + + // DEBUG_INFO(app.http_header.c_str()); + + if(std::regex_search(app.http_header, matches, content_length_regex)) { + app.file_length = stoi(matches[1].str()); + + DEBUG_INFO("Download started, file length: %u", app.file_length); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } else { + // Failed to extract the content length from the header, going into an error state + // TODO report the reason of the error + + app.prev_state = app.current_state; + app.current_state = APP_STATE_ERROR; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + } + break; + case APP_STATE_DOWNLOAD: + if(app.tcp_client->available() <= 0) { // no data available + break; + } + // DEBUG_INFO("reading: tot_len %6u, offset %6u", app.tcp_client->p->tot_len, app.tcp_client->pbuf_offset); + bytes_read = app.tcp_client->read(app.buffer, APP_BUFFER_SIZE); + // DEBUG_INFO("read %6u", bytes_read); + + if(bytes_read > 0) { + app.downloaded_bytes += bytes_read; + app.speed_bytes += bytes_read; + + // dump_buffer(app.buffer, APP_BUFFER_SIZE, 4, 128); +#ifdef CHECK_PAYLOAD + // if(!verify_buffer_sequential_4B( + if(!verify_buffer_sequential_faster_4B( + app.buffer, + bytes_read, + app.payload_verify_offset, + app.payload_verify_excess, + app.payload_verify_excess_len, + false)) { + + DEBUG_INFO("Payload verification failed"); + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FAILED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } +#endif // CHECK_PAYLOAD + } + + if(app.downloaded_bytes == app.file_length) { + app.last_value = + *(app.buffer + bytes_read - 4) << 24 | + *(app.buffer + bytes_read - 3) << 16 | + *(app.buffer + bytes_read - 2) << 8 | + *(app.buffer + bytes_read - 1); + + // if the download of the counter file is correct the last value should be + // the size of the file/4 -1 + if(app.last_value == (app.downloaded_bytes/4 - 1)) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FINISHED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } else { + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FAILED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + } + break; + + case APP_STATE_DOWNLOAD_FAILED: + // TODO report error in file download and close the connection + app.prev_state = app.current_state; + app.current_state = APP_STATE_ERROR; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_DOWNLOAD_FINISHED: + DEBUG_INFO("Download finished: %uMB", app.downloaded_bytes>>20); + DEBUG_INFO("Last value in the buffer: 0x%08X", app.last_value); + application_final_report(); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_RESET; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_ERROR: + // The app reached an expected error state + // TODO report this state and go in the default, status not defined handler to reset the state + case APP_STATE_RESET: + // in this state we reset the application and we start back from the beginning + + reset_app(app); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + } +} + +// application stats +void application_report(bool force) { + if(force || app.current_state == APP_STATE_PARSE_HEADER || app.current_state == APP_STATE_DOWNLOAD) { + + // float speed_conversion_factor = 1e3/(1<<10); + float speed_conversion_factor = 8*1e3/float(1<<20); + float elapsed = millis()-app.speed_start; + + float speed = (app.speed_bytes / elapsed) * speed_conversion_factor; + DEBUG_INFO("Application layer: %12u/%12u speed: %.2f Mbit/s", app.downloaded_bytes, app.file_length, speed); + + app.speed_start = millis(); + app.speed_bytes = 0; + } +} + +void application_final_report() { + // float speed_conversion_factor = 10e3/(1<<10); + float speed_conversion_factor = 1e3*8/float(1<<20); + + float elapsed = millis()-app.start; + float speed = (app.downloaded_bytes / elapsed) * speed_conversion_factor; + DEBUG_INFO( + "Application layer: Downloaded %u MB in %.2fs average speed: %.2f Mbit/s", + app.downloaded_bytes>>20, elapsed/1000, speed); +} + +// payload checking function +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print) { + size_t i=0; + bool res = true; + uint32_t value=0, first=0; + + if(excess_len > 0) { + uint8_t j=0; + for(; j 0) { + // the first value needs to be taken from the excess bytes of the previous buffer and the first of this + uint8_t j=0; + for(; j>>>>>>"); + for(uint8_t *p=b; p>>>>>>"); + for(uint8_t *p=b; p +#include +#include +#include + +// #define CNETIF_STATS_ENABLED +// #include "CNetifStats.h" + +#ifdef CNETIF_STATS_ENABLED +#define STATS_BUFFER_SIZE 1000 +char cnetif_stats_buffer[STATS_BUFFER_SIZE]; +// netif_stats _stats; +#endif // CNETIF_STATS_ENABLED + +// #define ETHER_CFG_PARAM_CHECKING_ENABLE +// Renesas libraries + +#include "IPAddress.h" + +// IPAddress default_ip("192.168.10.130"); +// IPAddress default_nm("255.255.255.0"); +// IPAddress default_gw("192.168.10.1"); +ip_addr_t ip; +ip_addr_t nm; +ip_addr_t gw; + +// FspTimer timer; + +#define CHECK_PAYLOAD + +#define LOOP_MIN_DURATION 100 // us + +/* --------------------------------------- */ +void timer_cb(timer_callback_args_t *arg); +void application(); +void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks=4, uint8_t cols=16); +void dump_buffer_char(uint8_t* b, uint32_t len); +void application_report(bool force=false); +bool verify_buffer_sequential_faster_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print= false); +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print=false); +void application_final_report(); +uint64_t debug_start; +/* --------------------------------------- */ + +SoftAPLWIPNetworkInterface C33WifiIface; + +void setup() { + Serial.begin(115200); + while(!Serial); + + Serial.println("Renesas file download example"); + // lwip setup + lwip_init(); // TODO move this inside the network stack init + LWIPNetworkStack::getInstance(); // TODO make this automatic + + DEBUG_INFO("Setting up netif"); + auto res = C33WifiIface.begin(); + DEBUG_INFO("%d", res); + + DEBUG_INFO("Starting AP"); + while((res=C33WifiIface.startSoftAp("testAP", "123456789", 5)) != ESP_CONTROL_OK) { + DEBUG_INFO("Connection failed retry: %d", res); + delay(1000); + } + DEBUG_INFO("AP started"); + + // setup netif + // IP_ADDR4(&ip, 192, 168, 10, 130); + // IP_ADDR4(&nm, 255, 255, 255, 0); + // IP_ADDR4(&gw, 192, 168, 10, 1); + + DEBUG_INFO("Begin of reception\n\n"); + debug_start = millis(); +} + +uint32_t counter =0; +void loop() { + + uint32_t start = micros(); +#ifndef NETWORKSTACK_USE_TIMER + LWIPNetworkStack::getInstance().task(); +#endif + if(millis() - debug_start > 3000) { // print the debug _stats every x second + // DEBUG_INFO("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + DEBUG_INFO("time: %12ums", millis()); + // DEBUG_INFO("memory: %12u bytes \tmin: %12u bytes \tmax: %12u bytes", + // memory_used, memory_used_min, memory_used_max); + DEBUG_INFO("loop counter %u\n", counter);\ + +#ifdef CNETIF_STATS_ENABLED + netif_stats_sprintf(cnetif_stats_buffer, C33WifiIface.stats, STATS_BUFFER_SIZE, (8*1e6)/(1<<20), "Mbit/s"); + // __disable_irq(); + arduino::lock(); + NETIF_STATS_RESET_AVERAGES(C33WifiIface.stats); + // __enable_irq(); + arduino::unlock(); + + DEBUG_INFO(cnetif_stats_buffer); +#endif // CNETIF_STATS_ENABLED + // DEBUG_INFO("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + + counter = 0; + // reset some counters + debug_start = millis(); + } + + counter++; +} \ No newline at end of file diff --git a/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/arduino_secrets.h b/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/arduino_secrets.h new file mode 100644 index 00000000..0c9fdd55 --- /dev/null +++ b/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino b/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino new file mode 100644 index 00000000..071f4eec --- /dev/null +++ b/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino @@ -0,0 +1,547 @@ +#include +#include +#include +#include +#include "arduino_secrets.h" +#include + +// #define CNETIF_STATS_ENABLED +// #include "CNetifStats.h" + +#ifdef CNETIF_STATS_ENABLED +#define STATS_BUFFER_SIZE 1000 +char cnetif_stats_buffer[STATS_BUFFER_SIZE]; +// netif_stats _stats; +#endif // CNETIF_STATS_ENABLED + +static char const SSID[] = SECRET_SSID; /* your network SSID (name) */ +static char const PASS[] = SECRET_PASS; /* your network password (use for WPA, or use as key for WEP) */ + +#define CHECK_PAYLOAD + +/* --------------------------------------- */ +void timer_cb(timer_callback_args_t *arg); +void application(); +void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks=4, uint8_t cols=16); +void dump_buffer_char(uint8_t* b, uint32_t len); +void application_report(bool force=false); +bool verify_buffer_sequential_faster_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print= false); +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print=false); +void application_final_report(); +uint64_t debug_start; +/* --------------------------------------- */ + +void setup() { + Serial.begin(115200); + while(!Serial); + + Serial.println("Renesas file download example"); + + int res = 0; + DEBUG_INFO("Connecting to AP"); + while((res=WiFi.begin(SSID, SECRET_PASS)) != 1) { + DEBUG_INFO("Connection failed retry: %d", res); + delay(1000); + } + DEBUG_INFO("Connected to AP"); + + DEBUG_INFO("Begin of reception\n\n"); + debug_start = millis(); +} + +uint32_t counter=0; +void loop() { + // __disable_irq(); + uint32_t start = micros(); +#ifndef LWIP_USE_TIMER + CLwipIf::getInstance().task(); +#endif + // Handle application FSM + application(); + + if(millis() - debug_start > 3000) { // print the debug _stats every x second + // DEBUG_INFO("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + DEBUG_INFO("time: %12ums", millis()); + // DEBUG_INFO("memory: %12u bytes \tmin: %12u bytes \tmax: %12u bytes", + // memory_used, memory_used_min, memory_used_max); + DEBUG_INFO("loop counter %u\n", counter); + application_report(); + + +#ifdef CNETIF_STATS_ENABLED + netif_stats_sprintf(cnetif_stats_buffer, WiFi.stats, STATS_BUFFER_SIZE, (8*1e6)/(1<<20), "Mbit/s"); + // __disable_irq(); + arduino::lock(); + NETIF_STATS_RESET_AVERAGES(WiFi.stats); + // __enable_irq(); + arduino::unlock(); + + DEBUG_INFO(cnetif_stats_buffer); +#endif // CNETIF_STATS_ENABLED + // DEBUG_INFO("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + + counter = 0; + // reset some counters + debug_start = millis(); + } + counter++; +} + +// Application level Stuff +enum app_state_t: uint8_t { + APP_STATE_NONE = 0, + APP_STATE_LINK_UP, + APP_STATE_LINK_DOWN, + APP_STATE_IFACE_UP, + APP_STATE_CONNECTING, + APP_STATE_CONNECTED, + APP_STATE_PARSE_HEADER, + APP_STATE_DOWNLOAD, + APP_STATE_DOWNLOAD_FAILED, + APP_STATE_DOWNLOAD_FINISHED, + APP_STATE_ERROR, + APP_STATE_RESET +}; + +static const char* state_strings[] = { + "APP_STATE_NONE", + "APP_STATE_LINK_UP", + "APP_STATE_LINK_DOWN", + "APP_STATE_IFACE_UP", + "APP_STATE_CONNECTING", + "APP_STATE_CONNECTED", + "APP_STATE_PARSE_HEADER", + "APP_STATE_DOWNLOAD", + "APP_STATE_DOWNLOAD_FAILED", + "APP_STATE_DOWNLOAD_FINISHED", + "APP_STATE_ERROR", + "APP_STATE_RESET" +}; + +#define APP_BUFFER_SIZE 1*1024 + + +struct App { + app_state_t current_state=APP_STATE_NONE; + app_state_t prev_state=APP_STATE_NONE; + + lwipClient *tcp_client; + uint16_t port = 8000; + IPAddress server_ip = IPAddress(192, 168, 10, 250); + + uint8_t buffer[APP_BUFFER_SIZE]; + + size_t file_length=0; + size_t downloaded_bytes=0; + std::string http_header; + + // stats related variables + uint32_t start = 0; + uint32_t speed_start = 0; + uint32_t speed_bytes = 0; + + // payload verification parameters + uint32_t payload_verify_offset=0; + uint8_t payload_verify_excess[4]={}; // this should be 3, but there are bugs + uint8_t payload_verify_excess_len=0; + uint32_t last_value=0; +} app; + +void init_app(struct App& app) { + app.file_length = 0; + app.http_header = ""; + app.downloaded_bytes = 0; + app.start = 0; + app.payload_verify_excess_len = 0; + app.payload_verify_offset = 0; + app.last_value=0; + app.speed_bytes = 0; +} + +void reset_app(struct App& app) { + init_app(app); + + if(app.tcp_client != nullptr) { + delete app.tcp_client; + } +} + +const char* http_request = "GET /test-4M HTTP/1.1\nHost: 192.168.10.250\nConnection: close\n\n"; + +void application() { + bool found = false; + uint16_t bytes_read=0; + + switch(app.current_state) { + case APP_STATE_NONE: + init_app(app); + + // TODO we are not handling link connection and disconnection + app.prev_state = app.current_state; + app.current_state = APP_STATE_LINK_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_LINK_UP: + if(WiFiStation.isDhcpAcquired()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + break; + case APP_STATE_IFACE_UP: + // The link is up we connect to the server + app.tcp_client = new lwipClient; + + // Connection details: + app.tcp_client->connect(app.server_ip, app.port); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTING; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_CONNECTING: + // do nothing, until the TCP connection is established + // TODO handle timeout for connection and go to error state + if(app.tcp_client->connected()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + + break; + + case APP_STATE_CONNECTED: + app.tcp_client->write((uint8_t*)http_request, strlen(http_request)); + app.start = millis(); + app.speed_start = app.start; + + app.prev_state = app.current_state; + app.current_state = APP_STATE_PARSE_HEADER; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_PARSE_HEADER: + // FIXME + bytes_read = app.tcp_client->read_until_token(app.buffer, APP_BUFFER_SIZE, "\r\n\r\n", found); + // DEBUG_INFO("%s", app.http_header.c_str()); + + if(bytes_read>0) { + // put the buffer into an http header string + std::string chunk((char*)app.buffer, bytes_read); + app.http_header += chunk; + app.speed_bytes += bytes_read; + DEBUG_INFO("%s", app.http_header.c_str()); + } + + if(found) { // FIXME reduce indentation level + // we found the http terminating token, go to the next app phase if we extracted the file len + // otherwise go in error phase + + // Parse the http header and gather information needed for the download + // dump_buffer_char(app.buffer, APP_BUFFER_SIZE); + + std::regex content_length_regex("Content-Length: ([0-9]+)", std::regex::icase); + std::smatch matches; + + // DEBUG_INFO(app.http_header.c_str()); + + if(std::regex_search(app.http_header, matches, content_length_regex)) { + app.file_length = stoi(matches[1].str()); + + DEBUG_INFO("Download started, file length: %u", app.file_length); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } else { + // Failed to extract the content length from the header, going into an error state + // TODO report the reason of the error + + app.prev_state = app.current_state; + app.current_state = APP_STATE_ERROR; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + } + break; + case APP_STATE_DOWNLOAD: + if(app.tcp_client->available() <= 0) { // no data available + break; + } + // DEBUG_INFO("reading: tot_len %6u, offset %6u", app.tcp_client->p->tot_len, app.tcp_client->pbuf_offset); + bytes_read = app.tcp_client->read(app.buffer, APP_BUFFER_SIZE); + // DEBUG_INFO("read %6u", bytes_read); + + if(bytes_read > 0) { + app.downloaded_bytes += bytes_read; + app.speed_bytes += bytes_read; + + // dump_buffer(app.buffer, APP_BUFFER_SIZE, 4, 128); +#ifdef CHECK_PAYLOAD + // if(!verify_buffer_sequential_4B( + if(!verify_buffer_sequential_faster_4B( + app.buffer, + bytes_read, + app.payload_verify_offset, + app.payload_verify_excess, + app.payload_verify_excess_len, + false)) { + + DEBUG_INFO("Payload verification failed"); + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FAILED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } +#endif // CHECK_PAYLOAD + } + + if(app.downloaded_bytes == app.file_length) { + app.last_value = + *(app.buffer + bytes_read - 4) << 24 | + *(app.buffer + bytes_read - 3) << 16 | + *(app.buffer + bytes_read - 2) << 8 | + *(app.buffer + bytes_read - 1); + + // if the download of the counter file is correct the last value should be + // the size of the file/4 -1 + if(app.last_value == (app.downloaded_bytes/4 - 1)) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FINISHED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } else { + app.prev_state = app.current_state; + app.current_state = APP_STATE_DOWNLOAD_FAILED; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + } + break; + + case APP_STATE_DOWNLOAD_FAILED: + // TODO report error in file download and close the connection + app.prev_state = app.current_state; + app.current_state = APP_STATE_ERROR; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_DOWNLOAD_FINISHED: + DEBUG_INFO("Download finished: %uMB", app.downloaded_bytes>>20); + DEBUG_INFO("Last value in the buffer: 0x%08X", app.last_value); + application_final_report(); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_RESET; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_ERROR: + // The app reached an expected error state + // TODO report this state and go in the default, status not defined handler to reset the state + case APP_STATE_RESET: + // in this state we reset the application and we start back from the beginning + + reset_app(app); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + } +} + +// application stats +void application_report(bool force) { + if(force || app.current_state == APP_STATE_PARSE_HEADER || app.current_state == APP_STATE_DOWNLOAD) { + + // float speed_conversion_factor = 1e3/(1<<10); + float speed_conversion_factor = 8*1e3/float(1<<20); + float elapsed = millis()-app.speed_start; + + float speed = (app.speed_bytes / elapsed) * speed_conversion_factor; + DEBUG_INFO("Application layer: %12u/%12u speed: %.2f Mbit/s", app.downloaded_bytes, app.file_length, speed); + + app.speed_start = millis(); + app.speed_bytes = 0; + } +} + +void application_final_report() { + // float speed_conversion_factor = 10e3/(1<<10); + float speed_conversion_factor = 1e3*8/float(1<<20); + + float elapsed = millis()-app.start; + float speed = (app.downloaded_bytes / elapsed) * speed_conversion_factor; + DEBUG_INFO( + "Application layer: Downloaded %u MB in %.2fs average speed: %.2f Mbit/s", + app.downloaded_bytes>>20, elapsed/1000, speed); +} + +// payload checking function +bool verify_buffer_sequential_4B(uint8_t *buffer, size_t len, uint32_t& offset, uint8_t *excess, uint8_t &excess_len, bool print) { + size_t i=0; + bool res = true; + uint32_t value=0, first=0; + + if(excess_len > 0) { + uint8_t j=0; + for(; j 0) { + // the first value needs to be taken from the excess bytes of the previous buffer and the first of this + uint8_t j=0; + for(; j>>>>>>"); + for(uint8_t *p=b; p>>>>>>"); + for(uint8_t *p=b; p Date: Tue, 23 Jan 2024 17:15:05 +0100 Subject: [PATCH 66/79] fixing connection issue on Ethernet and Wifi Client when host is passed --- libraries/Ethernet/src/EthernetClient.h | 8 ++++++++ libraries/WiFi/src/WiFiClient.h | 8 ++++++++ libraries/lwIpWrapper/src/CNetIf.cpp | 8 ++++++++ libraries/lwIpWrapper/src/CNetIf.h | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/EthernetClient.h b/libraries/Ethernet/src/EthernetClient.h index 8d648b57..fe8edb80 100644 --- a/libraries/Ethernet/src/EthernetClient.h +++ b/libraries/Ethernet/src/EthernetClient.h @@ -14,6 +14,14 @@ class EthernetClient : public lwipClient { this->bindCNetIf(Ethernet); } + int connect(const char* host, uint16_t port) { + auto res = lwipClient::connect(host, port); + + this->bindCNetIf(Ethernet); + + return res; + } + int connect(IPAddress ip, uint16_t port) { auto res = lwipClient::connect(ip, port); diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index cad993d3..414012de 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -14,6 +14,14 @@ class WiFiClient: public lwipClient { this->bindCNetIf(WiFiStation); } + int connect(const char* host, uint16_t port) { + auto res = lwipClient::connect(host, port); + + this->bindCNetIf(WiFiStation); + + return res; + } + int connect(IPAddress ip, uint16_t port) { auto res = lwipClient::connect(ip, port); diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 1b33457c..eee9f3de 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -459,6 +459,14 @@ bool CNetIf::dhcpRenew() { #endif +IPAddress CNetIf::dnsServerIP() { +#if LWIP_DNS + return CLwipIf::getInstance().getDns(0); +#else + return INADDR_NONE; +#endif +} + /* ########################################################################## * ETHERNET NETWORK INTERFACE CLASS * ########################################################################## */ diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index fc7bf876..7fa0e79a 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -167,7 +167,7 @@ class CNetIf: public NetworkInterface { IPAddress localIP() { return IPAddress(this->getIpAdd()); } IPAddress subnetMask() { return IPAddress(this->getNmAdd()); } IPAddress gatewayIP() { return IPAddress(this->getGwAdd()); } - IPAddress dnsServerIP() { /* FIXME understand where dns should be managed */} + IPAddress dnsServerIP(); void config(IPAddress _ip, IPAddress _gw, IPAddress _nm); From 3bbaccd940afa541f0681cfae7b9f2c7448d0151 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 23 Jan 2024 17:29:35 +0100 Subject: [PATCH 67/79] exporting Network stack synchronization to lwipClient --- libraries/lwIpWrapper/src/CNetIf.cpp | 36 ++++++++++++------------ libraries/lwIpWrapper/src/CNetIf.h | 10 +++---- libraries/lwIpWrapper/src/lwipClient.cpp | 9 +++++- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index eee9f3de..adb91931 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -342,11 +342,11 @@ int CNetIf::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress &gw) this->dhcpStart(); - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); while(!this->isDhcpAcquired()) { CLwipIf::getInstance().task(); } - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); } #endif @@ -638,9 +638,9 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { time_num++; } - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); rv = CEspControl::getInstance().setWifiMode(WIFI_MODE_STA); - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); if((rv=this->scanForAp()) != WL_SCAN_COMPLETED) { rv = -2; @@ -668,7 +668,7 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { memset(ap.bssid, 0x00, BSSID_LENGTH); memcpy(ap.bssid, access_points[best_index].bssid, BSSID_LENGTH); - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); rv=CEspControl::getInstance().connectAccessPoint(ap); if (rv == ESP_CONTROL_OK) { @@ -680,7 +680,7 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { } else { wifi_status = WL_CONNECT_FAILED; } - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); } exit: @@ -690,10 +690,10 @@ int CWifiStation::connectToAP(const char* ssid, const char *passphrase) { int CWifiStation::scanForAp() { access_points.clear(); - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); int res = CEspControl::getInstance().getAccessPointScanList(access_points); - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); if (res == ESP_CONTROL_OK) { wifi_status = WL_SCAN_COMPLETED; @@ -707,11 +707,11 @@ int CWifiStation::scanForAp() { // disconnect int CWifiStation::disconnectFromAp() { - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); auto res = CEspControl::getInstance().disconnectAccessPoint(); - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); return res; } @@ -942,9 +942,9 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress time_num++; } - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); res = CEspControl::getInstance().setWifiMode(WIFI_MODE_AP); - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); CNetIf::begin( default_dhcp_server_ip, @@ -958,7 +958,7 @@ int CWifiSoftAp::begin(const IPAddress &ip, const IPAddress &nm, const IPAddress // TODO scan the other access point first and then set the channel if 0 // TODO there are requirements for ssid and password int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t channel) { - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); SoftApCfg_t cfg; strncpy((char*)cfg.ssid, ssid, SSID_LENGTH); @@ -991,7 +991,7 @@ int CWifiSoftAp::startSoftAp(const char* ssid, const char* passphrase, uint8_t c // wifi_status = WL_AP_FAILED; } - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); return rv; } @@ -1131,17 +1131,17 @@ uint8_t CWifiSoftAp::getChannel() { } int CWifiSoftAp::setLowPowerMode() { - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); auto res = CEspControl::getInstance().setPowerSaveMode(1); - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); return res; } int CWifiSoftAp::resetLowPowerMode() { - CLwipIf::getInstance().sync_timer(); + CLwipIf::getInstance().syncTimer(); auto res = CEspControl::getInstance().setPowerSaveMode(1); - CLwipIf::getInstance().enable_timer(); + CLwipIf::getInstance().enableTimer(); return res; } diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 7fa0e79a..29f37884 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -432,24 +432,24 @@ class CLwipIf { friend class CNetIf; friend class CWifiSoftAp; friend class CWifiStation; - +public: #ifdef LWIP_USE_TIMER FspTimer timer; - inline void sync_timer() { + inline void syncTimer() { timer.disable_overflow_irq(); this->task(); } - inline void enable_timer() { + inline void enableTimer() { timer.enable_overflow_irq(); } #else // LWIP_USE_TIMER - inline void sync_timer() { + inline void syncTimer() { this->task(); } - inline void enable_timer() { } + inline void enableTimer() { } #endif // LWIP_USE_TIMER }; diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 1147a956..492e1dbf 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -101,6 +101,7 @@ int lwipClient::connect(IPAddress ip, uint16_t port) { // the connect method is only connected when trying to connect a client to a server // and not when a client is created out of a listening socket + CLwipIf::getInstance().syncTimer(); this->tcp_info->pcb = tcp_new(); if(this->tcp_info->pcb == nullptr) { @@ -124,7 +125,13 @@ int lwipClient::connect(IPAddress ip, uint16_t port) { this->tcp_info->pcb, &this->_ip, port, // FIXME check if _ip gets copied _lwip_tcp_connected_callback // FIXME we need to define a static private function ); - return err; + + while(!connected()) { + CLwipIf::getInstance().task(); + } + CLwipIf::getInstance().enableTimer(); + + return err == ERR_OK? 1: -err; } err_t _lwip_tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err) { From c595cc07c680a215fcb0a76dffff9334dcab768f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 23 Jan 2024 17:29:54 +0100 Subject: [PATCH 68/79] fixing return codes --- libraries/lwIpWrapper/src/lwipClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 492e1dbf..02103ba1 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -89,7 +89,7 @@ int lwipClient::connect(const char* host, uint16_t port) { IPAddress remote_addr; int ret = CLwipIf::getInstance().getHostByName(host, remote_addr); // TODO test this - if (ret == 1) { + if (ret == 0) { return connect(remote_addr, port); } else { return 0; @@ -287,7 +287,7 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { tcp_output(this->tcp_info->pcb); arduino::unlock(); - return buffer - buffer_cursor; + return buffer_cursor - buffer; } int lwipClient::read() { From ec5ea837dc45651008a62d491be7f4914d2ba937 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 23 Jan 2024 17:30:46 +0100 Subject: [PATCH 69/79] deleting pbuf when partially consumed --- libraries/lwIpWrapper/src/lwipClient.cpp | 16 +++++++++++----- libraries/lwIpWrapper/src/lwipClient.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 02103ba1..019ea459 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -235,7 +235,7 @@ err_t lwipClient::recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err) if (p == NULL) { // Remote host has closed the connection -> close from our side - this->stop(); + this->close_pcb(); return ERR_OK; } @@ -345,7 +345,7 @@ void lwipClient::flush() { tcp_output(this->tcp_info->pcb); } -void lwipClient::stop() { +void lwipClient::close_pcb() { if(this->tcp_info->pcb != nullptr) { tcp_recv(this->tcp_info->pcb, nullptr); tcp_sent(this->tcp_info->pcb, nullptr); @@ -360,12 +360,18 @@ void lwipClient::stop() { // FIXME if err != ERR_OK retry, there may be memory issues, retry? } +} +void lwipClient::stop() { + this->close_pcb(); // reset all the other variables in this class - // if(tcp->p != nullptr) { - // pbuf_free(tcp->p); // FIXME it happens that a pbuf, with ref == 0 is added for some reason - // } + if(this->tcp_info->pbuf_head != nullptr) { + pbuf_free(this->tcp_info->pbuf_head); // FIXME it happens that a pbuf, with ref == 0 is added for some reason + this->tcp_info->pbuf_head = nullptr; + } + this->tcp_info->pbuf_offset = 0; + if(this->tcp_info->server != nullptr) { // need to first make the server point to nullptr, then remove the client, can cause infinite recursion auto server = this->tcp_info->server; diff --git a/libraries/lwIpWrapper/src/lwipClient.h b/libraries/lwIpWrapper/src/lwipClient.h index 446c4288..d7a7c0bd 100644 --- a/libraries/lwIpWrapper/src/lwipClient.h +++ b/libraries/lwIpWrapper/src/lwipClient.h @@ -108,6 +108,7 @@ class lwipClient : public arduino::Client { friend err_t _lwip_tcp_recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err); friend err_t _lwip_tcp_connected_callback(void* arg, struct tcp_pcb* tpcb, err_t err); + void close_pcb(); }; inline const lwipClient CLIENT_NONE(nullptr, nullptr); \ No newline at end of file From 564fcfc4aac58539df0b9b780a32081609318681 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Jan 2024 11:45:34 +0100 Subject: [PATCH 70/79] Changed memory alignemnt according to renesas specifications --- extras/net/lwipopts.h | 2 +- .../lwIpWrapper/src/cortex-m33/liblwIP.a | Bin 277056 -> 277056 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/net/lwipopts.h b/extras/net/lwipopts.h index b6acf324..15f22494 100644 --- a/extras/net/lwipopts.h +++ b/extras/net/lwipopts.h @@ -129,7 +129,7 @@ * 2 byte alignment -> #define MEM_ALIGNMENT 2 */ #ifndef MEM_ALIGNMENT -#define MEM_ALIGNMENT 4 +#define MEM_ALIGNMENT 32 #endif /** diff --git a/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a b/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a index 0009e3f547eccf14b47246cd35170fd3bcb855bf..33abbd5a46d48c79df1b7df23c543ff00a9449dd 100644 GIT binary patch delta 2957 zcmZWr3s4hB7{0yD15imuln?}R2IZw-Vq(-$Ax4O%RIxI)0qKpx;Ao9wEBKsb>La68yU9JWk<8@w_Pg)@zkmP# z-@WtPReSELn}#VZhKWXt+0voEtr6}G=&v+-HQ+XDPXh_cc!_ob?nc^)C=_A21{q~a z&dMB@a4u2b6DQhnck&ujg^7_()N8o)C6)vcaAg!j4R@t1Q7$2eN5d2@ac&6|5p0yq z*3Yv89gF7W;%iWw%N^* z>%`BVPuG5LYxfp3Pz8I=Brol-#dQy@#@3@#%kh={xk8r?f;yNP(7~;4-KhNQfoZZH z4tt<`C`RpP*hdxF1DM}%JoKE@-9d)UuS}O`l+pOEtaA7mrgnYRj+^l`uj$ava;h91 zp?0gjIH|Zb)Nc5t7Y410y*7_8A!5@~nKqe<{b9-JRL&AFC4{lXt;>`3xP=fZ{fxfJ z_R#lcK&Ld9n%M`HMM>6#^Cex_`89i2$X#D>E*y-bDibj5vMM9Kwp8VCC#tT}U;(#h z{z0iMY~A8lv;FltQ;PNJgC|d^oC)0&6L*NB;&bBm5Awy8mWLQa*?oWg)=zcpgT<{5 z1_zpt|KTw~81X>)6%;jIm}`V_9v-*jzeAW$6~^lD$POMuH_olG_4&eUl-a4Azr9qZq8L^eS(wtSfKFkrRyIy=JW}oJ zr5NmOI_7m#S!R2?{c>n&Q#=#4bK4bm>j9u2!YyJxXnHQzNM{=gzeD%Ipt%xvq^(Dlmhc*`fpW+_IKA zQXWuUWq6a8v>y|9o-w?gQn);KgG@}8K+63wmZaeZ9kfgqNMplhT5i$(3HcB90{F7Tr??q3D7_TCHCRMkhx?!g?Rf>fm@Go!ZHt(dpnRZ+Abf;;2+-q3 zAe|KvX$`uv1{@nJ(e`$NpjMnk+;n-tq^O%G7lA`O9mb+rez1Iiz&1r9yL1!S)FR@_ z=%rIo;bTydBtocJMN1A$=+0nrR+voAHfYHiKJR9V!X`emsAD)SrPhQ#$Rrs!(A5CF zkVBsoD1g0zZsI;vR}O`18pV$ADoi1I{C@ji+1wsW1& z*y7Bzu8C$VVvDih$0Qbc!J(<2M>8$*Hm@gnyv9FGqy}$m+|=K8t&6nfd4F!{&&zEl zd3=Q%TKi)sz9lg}7VURrERlCNTGB@5g~vMg5?JJIjJCDYbHvsYQ@ZK^K@*zoXcsBV zhd0ziV*JuxJJNq?2ab_E-ZuUu#^jN&5%yM|76nhyS>o4;8R2c*Ansr@YJM1Pw8#uM z=BlS;jEQM*EkLJe_^a4xW`sAyX8>g?Fed1z-6@?WSq*SqN`?vO-FWCFo}hLaTnW&{ zf$%tqdJ^Fz7_~=UJ*)$+0yR{ibxH6PNyQFU0MwftBN%pz(W2B?)R~LjpfA(miDx`u z^cn+yCs8a}M25iIZpn_d#prl~653-S~w3JSp~Rw!fmm=dDE)S9V7Ma8(8uxSJzo0~6^ zJJ-Yq4rhp)N}yGaIuMNW?OfH(l+9_AsYsZvY(6UUvA_5Bwg+63|F-{kzyJN8lXg5- zc05+rM#wYtY5I)xtY+QAFe(3=bZlm8kaef#D)Io@^=_a$@{$Pf4D+BgiQJl_J?}xy zKvP>|bY~QTnV?IOmWI>%*1U24wCX6!6T}Sn3%wc#s+w_HB_bO0C`4+=J_LO(7yBG)48_0f@_va0zOEQW{d|=bN z6csH`D(C%S*SlogTO}irgnPdvHC6H6-m+tWN47syS5(8hDZ@118k%e=RZPl}YoX=M z21WZ&6IhQ5FM=m`x@367<;Z9!#=9*6Ny**L$&yYh*t4CCR_O@jUY5iKD6T*@?9A}P zy$UY1beMGbbQXTiC>@cisMuDvzsHXiA{J<-RVxdcT}?TjNZD;s2c3A=vC7l*e3Z;%fU9F+dzQQS&rx#{$&r2t&Li}&$ zwSx2e##Wc5GUbLlnZmMYq~KPRrNOhlEFQI6FO=P7k;-~x?n!zk+{Oh{;$BqZG3uPx z&tAP|;xpSBt)h)#{NfeI2H6#bMJ}y=`qLMcyEkL**@F541tgmcq6YB?QG&QXM`a8% z4!*S@VIXdNHpm{30+2|MNgyF0CJ-$*qA1B4xJVxC*$Af`tF8Kv&U-f147!FJx@|2| za@@A1epuh;3VB!S#GHJ4*E+pTZr3?;FiMKGF)>Q!wUC;g{ zr>Z4)Gub5Z=JiG1X#hLV9Y2n|x`oyu(wzr!z1ZBL7_h7Y_PQ72f^=adp^&Xpcv)AA z*aGa;qGr+B@=`X>_ipY2b|WGa=0ShG{GjdYL&d;rsiJuTCR*IE?IVVrR++w0ZRjA1%|fY-d}2VMT0c2aO4(Ej;5ZP2`<8 zNArZz{4P-#_b4%p^j>CT#lJC`B&v(8QhD;qBz1khRpT{S&DF2zEQ2EPCPXf?_=31J znFNl+=ZHkhXzbJ|yb+nBWLQSl_~D-hl79=N$%2D1N*b%X3g^uHdnooNTU7W;KL<0! z;~>VK7*3l)j@|>qGoXt5TKuEW2k)F@#o(J1*5^KmyW+6-Ac`G$lt^PxS&1)xlpa&r zK>xr;Upmc);sBeL*)KlNYsjW~!n~eLz~0M-&wT?T1qSTBl(Gn{Q&qBOVp*haB_0_d zYH$&S62}_+Z;Xg|wrc)2KCf9s*r4VH+N*#`zoRhj)mGS+L%2cb^#*+_7HiKkpLzg` zJ@`6q2=x*GIvpZv=EfGJCUq}yn?{8A4Xg^21gS-YY)_T=d=ls`j2-?e4<;X{OT44V L;!87)l{oN!@xY>Y From 6c5f0ea2fe32de53873291e2501cfe557785e178 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Jan 2024 14:37:59 +0100 Subject: [PATCH 71/79] improving examples --- .../ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino | 8 ++++++-- .../examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino | 5 ++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino index 521983ce..0e5dcca4 100644 --- a/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino +++ b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33/ethernet_bare_lwipc33.ino @@ -36,9 +36,13 @@ void setup() { Serial.println("Renesas file download example"); + IPAddress ip(192, 168, 10, 130); + IPAddress gw(192, 168, 10, 1); + IPAddress nm(255, 255, 255, 0); + DEBUG_INFO("Setting up netif"); - // Ethernet.begin(&ip, &nm, &gw); - Ethernet.begin(); + Ethernet.begin(ip, nm, gw); + // Ethernet.begin(); DEBUG_INFO("Begin of reception\n\n"); debug_start = millis(); diff --git a/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino b/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino index 071f4eec..fc9eca56 100644 --- a/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino +++ b/libraries/lwIpWrapper/examples/wifi_bare_lwipc33/wifi_bare_lwipc33.ino @@ -37,10 +37,9 @@ void setup() { Serial.println("Renesas file download example"); - int res = 0; DEBUG_INFO("Connecting to AP"); - while((res=WiFi.begin(SSID, SECRET_PASS)) != 1) { - DEBUG_INFO("Connection failed retry: %d", res); + while(WiFi.begin(SSID, SECRET_PASS) != WL_CONNECTED) { + DEBUG_INFO("Connection failed retry"); delay(1000); } DEBUG_INFO("Connected to AP"); From 6edeefe5a7e64edf9450aacafa4983e7ea427da2 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Jan 2024 14:39:29 +0100 Subject: [PATCH 72/79] setting dhcp acquired when dhcp server is informed of static ip --- libraries/lwIpWrapper/src/CNetIf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index adb91931..389e115a 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -432,6 +432,7 @@ void CNetIf::config(IPAddress _ip, IPAddress _gw, IPAddress _nm) { void CNetIf::dhcpNotUsed() { dhcp_inform(&this->ni); + dhcp_acquired = true; } bool CNetIf::isDhcpAcquired() { From 896f7caa8c286b8c74210e8a5e4ac7cb8830995f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Jan 2024 15:05:08 +0100 Subject: [PATCH 73/79] improving performances of ssl client --- libraries/SSLClient/src/ssl_client.cpp | 29 ++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/libraries/SSLClient/src/ssl_client.cpp b/libraries/SSLClient/src/ssl_client.cpp index 5a334ecd..ee254969 100644 --- a/libraries/SSLClient/src/ssl_client.cpp +++ b/libraries/SSLClient/src/ssl_client.cpp @@ -52,23 +52,30 @@ static int _handle_error(int err, const char * file, int line) */ static int client_net_recv( void *ctx, unsigned char *buf, size_t len ) { Client *client = (Client*)ctx; - if (!client) { + if (!client) { log_e("Uninitialised!"); return -1; } - + //if (!client->connected()) { // log_e("Not connected!"); // return -2; //} + if(client->available() == 0) { + log_d("Want to read %u", len); + return MBEDTLS_ERR_SSL_WANT_READ; + } int result = client->read(buf, len); log_d("SSL client RX res=%d len=%d", result, len); - if (result > 0) { - //esp_log_buffer_hexdump_internal("SSL.RD", buf, (uint16_t)result, ESP_LOG_VERBOSE); + if(result < 0) { + return MBEDTLS_ERR_SSL_WANT_READ; } - + // if (result > 0) { + //esp_log_buffer_hexdump_internal("SSL.RD", buf, (uint16_t)result, ESP_LOG_VERBOSE); + // } + return result; } @@ -121,20 +128,20 @@ int client_net_recv_timeout( void *ctx, unsigned char *buf, */ static int client_net_send( void *ctx, const unsigned char *buf, size_t len ) { Client *client = (Client*)ctx; - if (!client) { + if (!client) { log_e("Uninitialised!"); return -1; } - + //if (!client->connected()) { // log_e("Not connected!"); // return -2; //} - + //esp_log_buffer_hexdump_internal("SSL.WR", buf, (uint16_t)len, ESP_LOG_VERBOSE); - + int result = client->write(buf, len); - + log_d("SSL client TX res=%d len=%d", result, len); return result; } @@ -307,7 +314,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p log_v("Setting up IO callbacks..."); mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, ssl_client->client, - client_net_send, NULL, client_net_recv_timeout ); + client_net_send, client_net_recv, NULL ); log_v("Performing the SSL/TLS handshake..."); unsigned long handshake_start_time=millis(); From aa3c5a1a4dadbbd61eeaee0c211d70d63d300d79 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Jan 2024 15:22:21 +0100 Subject: [PATCH 74/79] fixing counter overflow in tcp send --- libraries/lwIpWrapper/src/lwipClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 019ea459..9aeb99cd 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -265,7 +265,7 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { arduino::lock(); uint8_t* buffer_cursor = (uint8_t*)buffer; - uint8_t bytes_to_send = 0; + uint16_t bytes_to_send = 0; do { bytes_to_send = min(size - (buffer - buffer_cursor), tcp_sndbuf(this->tcp_info->pcb)); @@ -282,7 +282,7 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { } else if(res == ERR_MEM) { // FIXME handle this: we get into this case only if the sent data cannot be put in the send queue } - } while(buffer_cursor < buffer + size); + } while(buffer_cursor - buffer < size); tcp_output(this->tcp_info->pcb); From 9e05471e73c4580998a1481cec1a92b639a560ab Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 25 Jan 2024 10:31:46 +0100 Subject: [PATCH 75/79] added tcp write example for tcp echo server --- .../ethernet_bare_lwipc33_write.ino | 301 ++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino diff --git a/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino new file mode 100644 index 00000000..42ed4238 --- /dev/null +++ b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino @@ -0,0 +1,301 @@ +#include +#include +#include +#include +#include + +// #define CNETIF_STATS_ENABLED +// #include "CNetifStats.h" + +#ifdef CNETIF_STATS_ENABLED +#define STATS_BUFFER_SIZE 1000 +char cnetif_stats_buffer[STATS_BUFFER_SIZE]; +// netif_stats _stats; +#endif // CNETIF_STATS_ENABLED + +#include +#include + +#define CHECK_PAYLOAD + +/* --------------------------------------- */ +void timer_cb(timer_callback_args_t *arg); +void application(); +void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks=4, uint8_t cols=16); +void dump_buffer_char(uint8_t* b, uint32_t len); +uint64_t debug_start; +/* --------------------------------------- */ + +void setup() { + Serial.begin(115200); + while(!Serial); + + Serial.println("Renesas file download example"); + + IPAddress ip(192, 168, 10, 130); + IPAddress gw(192, 168, 10, 1); + IPAddress nm(255, 255, 255, 0); + + DEBUG_INFO("Setting up netif"); + Ethernet.begin(ip, nm, gw); + // Ethernet.begin(); + + DEBUG_INFO("Begin of reception\n\n"); + debug_start = millis(); +} + +uint32_t counter=0; +void loop() { + // __disable_irq(); + uint32_t start = micros(); +#ifndef LWIP_USE_TIMER + CLwipIf::getInstance().task(); +#endif + // Handle application FSM + application(); + + if(millis() - debug_start > 3000) { // print the debug _stats every x second + // DEBUG_INFO("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + DEBUG_INFO("time: %12ums", millis()); + // DEBUG_INFO("memory: %12u bytes \tmin: %12u bytes \tmax: %12u bytes", + // memory_used, memory_used_min, memory_used_max); + DEBUG_INFO("loop counter %u\n", counter); + // application_report(); + +#ifdef CNETIF_STATS_ENABLED + netif_stats_sprintf(cnetif_stats_buffer, Ethernet.stats, STATS_BUFFER_SIZE, (8*1e6)/(1<<20), "Mbit/s"); + // __disable_irq(); + arduino::lock(); + NETIF_STATS_RESET_AVERAGES(Ethernet.stats); + // __enable_irq(); + arduino::unlock(); + + DEBUG_INFO(cnetif_stats_buffer); +#endif // CNETIF_STATS_ENABLED + // DEBUG_INFO("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + + counter = 0; + // reset some counters + debug_start = millis(); + } + counter++; +} + +// Application level Stuff +enum app_state_t: uint8_t { + APP_STATE_NONE = 0, + APP_STATE_LINK_UP, + APP_STATE_LINK_DOWN, + APP_STATE_IFACE_UP, + APP_STATE_CONNECTING, + APP_STATE_CONNECTED, + APP_STATE_SEND, + APP_STATE_RECEIVE, + APP_STATE_ERROR, + APP_STATE_RESET +}; + +static const char* state_strings[] = { + "APP_STATE_NONE", + "APP_STATE_LINK_UP", + "APP_STATE_LINK_DOWN", + "APP_STATE_IFACE_UP", + "APP_STATE_CONNECTING", + "APP_STATE_CONNECTED", + "APP_STATE_SEND", + "APP_STATE_RECEIVE", + "APP_STATE_ERROR", + "APP_STATE_RESET" +}; + +#define APP_BUFFER_SIZE 1*1024 + +typedef uint32_t counter_t; + +struct App { + app_state_t current_state=APP_STATE_NONE; + app_state_t prev_state=APP_STATE_NONE; + + lwipClient *tcp_client; + uint16_t port = 2000; + IPAddress server_ip = IPAddress(192, 168, 10, 250); + + counter_t counter; + uint8_t buffer[APP_BUFFER_SIZE]; + + size_t file_length=0; + size_t downloaded_bytes=0; + std::string http_header; + + // stats related variables + uint32_t start = 0; + uint32_t speed_start = 0; + uint32_t speed_bytes = 0; + + // payload verification parameters + uint32_t payload_verify_offset=0; + uint8_t payload_verify_excess[4]={}; // this should be 3, but there are bugs + uint8_t payload_verify_excess_len=0; + uint32_t last_value=0; +} app; + +void init_app(struct App& app) { + app.file_length = 0; + app.http_header = ""; + app.downloaded_bytes = 0; + app.start = 0; + app.payload_verify_excess_len = 0; + app.payload_verify_offset = 0; + app.last_value=0; + app.speed_bytes = 0; + app.counter = 0; +} + +void reset_app(struct App& app) { + init_app(app); + + if(app.tcp_client != nullptr) { + app.tcp_client->stop(); + // delete app.tcp_client; + } +} + +void application() { + bool found = false; + uint16_t bytes_read=0; + + switch(app.current_state) { + case APP_STATE_NONE: + init_app(app); + + // TODO we are not handling link connection and disconnection + app.prev_state = app.current_state; + app.current_state = APP_STATE_LINK_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_LINK_UP: + if(Ethernet.isDhcpAcquired()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + break; + case APP_STATE_IFACE_UP: + // The link is up we connect to the server + app.tcp_client = new lwipClient; + + // Connection details: + app.tcp_client->connect(app.server_ip, app.port); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_CONNECTING; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + + case APP_STATE_CONNECTING: + // do nothing, until the TCP connection is established + // TODO handle timeout for connection and go to error state + if(app.tcp_client->connected()) { + app.prev_state = app.current_state; + app.current_state = APP_STATE_SEND; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + } + + break; + + case APP_STATE_CONNECTED: + app.start = millis(); + app.speed_start = app.start; + + app.prev_state = app.current_state; + app.current_state = APP_STATE_SEND; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + case APP_STATE_SEND: { + int res = app.tcp_client->write((uint8_t*)&app.counter, sizeof(counter_t)); + DEBUG_INFO("counter sent, value 0x%08X, res: %d", app.counter, res); + + if(res == sizeof(counter_t)) { + app.counter++; + app.prev_state = app.current_state; + app.current_state = APP_STATE_RECEIVE; + // DEBUG_INFO("State changed: to %s, from %s", + // state_strings[app.current_state], + // state_strings[app.prev_state]); + } + break; + } + case APP_STATE_RECEIVE: { + counter_t read_counter; + bytes_read = app.tcp_client->read((uint8_t*)&read_counter, sizeof(counter_t)); + + if(bytes_read == sizeof(counter_t)) { + DEBUG_INFO("counter echoed, value 0x%08X", read_counter); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_SEND; + // DEBUG_INFO("State changed: to %s, from %s", + // state_strings[app.current_state], + // state_strings[app.prev_state]); + } + break; + } + case APP_STATE_ERROR: + // The app reached an expected error state + // TODO report this state and go in the default, status not defined handler to reset the state + case APP_STATE_RESET: + // in this state we reset the application and we start back from the beginning + + reset_app(app); + + app.prev_state = app.current_state; + app.current_state = APP_STATE_IFACE_UP; + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); + break; + } +} + +// Utility functions +void dump_buffer(uint8_t* b, uint32_t len, uint8_t blocks, uint8_t cols) { + + // TODO make sure blocks is less that cols + Serial.println("BUFFER >>>>>>>"); + for(uint8_t *p=b; p>>>>>>"); + for(uint8_t *p=b; p Date: Fri, 26 Jan 2024 10:09:32 +0100 Subject: [PATCH 76/79] changing synchronization to timer disable --- libraries/lwIpWrapper/src/CNetIf.cpp | 2 -- libraries/lwIpWrapper/src/lwipClient.cpp | 19 +++++++++---------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 389e115a..9d197690 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -126,9 +126,7 @@ void CLwipIf::task() { iface->task(); } - arduino::lock(); sys_check_timeouts(); - arduino::unlock(); } void CLwipIf::setDefaultIface(CNetIf* iface) { diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index 9aeb99cd..bd5e9255 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -239,7 +239,6 @@ err_t lwipClient::recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err) return ERR_OK; } - arduino::lock(); if(this->tcp_info->state == TCP_CONNECTED || this->tcp_info->state == TCP_ACCEPTED) { if (this->tcp_info->pbuf_head == nullptr) { // no need to increment the references of the pbuf, @@ -252,7 +251,6 @@ err_t lwipClient::recv_callback(struct tcp_pcb* tpcb, struct pbuf* p, err_t err) ret_err = ERR_OK; } - arduino::unlock(); return ret_err; } @@ -262,7 +260,7 @@ size_t lwipClient::write(uint8_t b) { } size_t lwipClient::write(const uint8_t* buffer, size_t size) { - arduino::lock(); + CLwipIf::getInstance().syncTimer(); uint8_t* buffer_cursor = (uint8_t*)buffer; uint16_t bytes_to_send = 0; @@ -286,7 +284,8 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { tcp_output(this->tcp_info->pcb); - arduino::unlock(); + CLwipIf::getInstance().enableTimer(); + return buffer_cursor - buffer; } @@ -312,14 +311,14 @@ int lwipClient::read(uint8_t* buffer, size_t size) { * meaning that across different calls of this function a pbuf could be partially copied * we need to account that */ - arduino::lock(); + CLwipIf::getInstance().syncTimer(); uint16_t copied = pbuf_copy_partial(this->tcp_info->pbuf_head, buffer, size, this->tcp_info->pbuf_offset); this->tcp_info->pbuf_head = free_pbuf_chain(this->tcp_info->pbuf_head, copied, &this->tcp_info->pbuf_offset); // acknowledge the received data tcp_recved(this->tcp_info->pcb, copied); - arduino::unlock(); + CLwipIf::getInstance().enableTimer(); return copied; } @@ -331,9 +330,9 @@ int lwipClient::peek() { return -1; } - arduino::lock(); + CLwipIf::getInstance().syncTimer(); b = pbuf_get_at(this->tcp_info->pbuf_head, 0); // TODO test this - arduino::unlock(); + CLwipIf::getInstance().enableTimer(); return b; } @@ -417,7 +416,7 @@ size_t lwipClient::read_until_token( if(buffer_size==0 || buffer==nullptr || this->tcp_info->pbuf_head==nullptr) { return 0; // TODO extend checks } - arduino::lock(); + CLwipIf::getInstance().syncTimer(); // TODO check that the buffer size is less than the token len uint16_t offset=this->tcp_info->pbuf_offset; @@ -456,7 +455,7 @@ size_t lwipClient::read_until_token( // acknowledge the received data tcp_recved(this->tcp_info->pcb, copied); - arduino::unlock(); + CLwipIf::getInstance().enableTimer(); return copied; } From e303948509363fff55b213284ade9d92e2cfe671 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 26 Jan 2024 10:11:41 +0100 Subject: [PATCH 77/79] improving write function to better handle memory errors and bigger buffers --- libraries/lwIpWrapper/src/lwipClient.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libraries/lwIpWrapper/src/lwipClient.cpp b/libraries/lwIpWrapper/src/lwipClient.cpp index bd5e9255..a2a533ce 100644 --- a/libraries/lwIpWrapper/src/lwipClient.cpp +++ b/libraries/lwIpWrapper/src/lwipClient.cpp @@ -266,8 +266,7 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { uint16_t bytes_to_send = 0; do { - bytes_to_send = min(size - (buffer - buffer_cursor), tcp_sndbuf(this->tcp_info->pcb)); - + bytes_to_send = min(size - (buffer_cursor - buffer), tcp_sndbuf(this->tcp_info->pcb)); /* * TODO: Look into the following flags, especially for write of 1 byte * TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack @@ -279,7 +278,17 @@ size_t lwipClient::write(const uint8_t* buffer, size_t size) { buffer_cursor += bytes_to_send; } else if(res == ERR_MEM) { // FIXME handle this: we get into this case only if the sent data cannot be put in the send queue + CLwipIf::getInstance().task(); + // break; + } else { + break; } + + // FIXME blocking call + while(tcp_sndbuf(this->tcp_info->pcb) == 0 && buffer_cursor - buffer < size) { + CLwipIf::getInstance().task(); + } + } while(buffer_cursor - buffer < size); tcp_output(this->tcp_info->pcb); From b58a521939e36cc1ada4897068604de1de370d35 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 26 Jan 2024 10:13:34 +0100 Subject: [PATCH 78/79] making dns resolution to work automatically when interrupts are disabled --- libraries/lwIpWrapper/src/CNetIf.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 9d197690..3bb16bca 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -226,9 +226,13 @@ int CLwipIf::getHostByName(const char* aHostname, IPAddress& aResult, bool execu while(res == 1 && !completed) { // DNS timeouts seems to be handled by lwip, no need to put one here delay(1); +#ifndef LWIP_USE_TIMER + this->task(); +#else // LWIP_USE_TIMER if(execute_task) { this->task(); } +#endif // LWIP_USE_TIMER } return res == 1 ? 0 : res; From c28b4bd391bac9d0ce1b53eae7d2f00e6e614fa5 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Fri, 26 Jan 2024 11:14:11 +0100 Subject: [PATCH 79/79] improving example --- .../ethernet_bare_lwipc33_write.ino | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino index 42ed4238..4057602c 100644 --- a/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino +++ b/libraries/lwIpWrapper/examples/ethernet_bare_lwipc33_write/ethernet_bare_lwipc33_write.ino @@ -35,9 +35,10 @@ void setup() { IPAddress ip(192, 168, 10, 130); IPAddress gw(192, 168, 10, 1); IPAddress nm(255, 255, 255, 0); + IPAddress dns(8, 8, 8, 8); DEBUG_INFO("Setting up netif"); - Ethernet.begin(ip, nm, gw); + Ethernet.begin(ip, nm, gw, dns); // Ethernet.begin(); DEBUG_INFO("Begin of reception\n\n"); @@ -160,9 +161,9 @@ void reset_app(struct App& app) { } } +uint16_t bytes_read=0; void application() { bool found = false; - uint16_t bytes_read=0; switch(app.current_state) { case APP_STATE_NONE: @@ -189,8 +190,11 @@ void application() { // The link is up we connect to the server app.tcp_client = new lwipClient; + memset(app.buffer, 0x66, APP_BUFFER_SIZE); + // Connection details: app.tcp_client->connect(app.server_ip, app.port); + // app.tcp_client->connect("tcpbin.com", 4242); app.prev_state = app.current_state; app.current_state = APP_STATE_CONNECTING; @@ -223,31 +227,35 @@ void application() { state_strings[app.prev_state]); break; case APP_STATE_SEND: { - int res = app.tcp_client->write((uint8_t*)&app.counter, sizeof(counter_t)); - DEBUG_INFO("counter sent, value 0x%08X, res: %d", app.counter, res); + int res = app.tcp_client->write(app.buffer, APP_BUFFER_SIZE); + DEBUG_INFO("buffer sent res: %d", res); - if(res == sizeof(counter_t)) { - app.counter++; + if(res == APP_BUFFER_SIZE) { app.prev_state = app.current_state; app.current_state = APP_STATE_RECEIVE; - // DEBUG_INFO("State changed: to %s, from %s", - // state_strings[app.current_state], - // state_strings[app.prev_state]); + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); } break; } case APP_STATE_RECEIVE: { - counter_t read_counter; - bytes_read = app.tcp_client->read((uint8_t*)&read_counter, sizeof(counter_t)); + int res = app.tcp_client->read(app.buffer, APP_BUFFER_SIZE); - if(bytes_read == sizeof(counter_t)) { - DEBUG_INFO("counter echoed, value 0x%08X", read_counter); + if(res > 0) { + bytes_read += res; + DEBUG_INFO("received %d bytes", res); + } + + if(bytes_read == APP_BUFFER_SIZE) { + DEBUG_INFO("buffer received: %d", bytes_read); + bytes_read = 0; app.prev_state = app.current_state; app.current_state = APP_STATE_SEND; - // DEBUG_INFO("State changed: to %s, from %s", - // state_strings[app.current_state], - // state_strings[app.prev_state]); + DEBUG_INFO("State changed: to %s, from %s", + state_strings[app.current_state], + state_strings[app.prev_state]); } break; }