mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-07 06:01:35 +03:00
more lwIP physical interfaces (#6680)
This commit adds W5500 W5100 and ENC28j60 drivers from @njh with credits They are available in libraries/ An example is added in W5500 examples directory plus: * Extract dhcp server from lwip2 and add it to the core as a class. It must always be present, it is linked and can be called by fw on boot. So it cannot be stored in a library. * ethernet: static or dhcp works * PPPServer: example * bring WiFi.config() to the lwIP generic interface (argument reorder common function) * move hostname() from WiFI-STA to generic interface * remove non readable characters from dhcp-server comments * dhcp-server: magic_cookie is part of bootp rfc * fixes from https://github.com/d-a-v/W5500lwIP/issues/17 * enable lwip_hook_dhcp_parse_option() * +ethernet tcp client example in w5500 library examples
This commit is contained in:
64
cores/esp8266/LwipDhcpServer-NonOS.cpp
Normal file
64
cores/esp8266/LwipDhcpServer-NonOS.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
lwIPDhcpServer-NonOS.cpp - DHCP server wrapper
|
||||
|
||||
Copyright (c) 2020 esp8266 arduino. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// STARTS/STOPS DHCP SERVER ON WIFI AP INTERFACE
|
||||
// these functions must exists as-is with "C" interface,
|
||||
// nonos-sdk calls them at boot time and later
|
||||
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
|
||||
#include <lwip/netif.h>
|
||||
#include "LwipDhcpServer.h"
|
||||
|
||||
extern netif netif_git[2];
|
||||
|
||||
// global DHCP instance for softAP interface
|
||||
DhcpServer dhcpSoftAP(&netif_git[SOFTAP_IF]);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void dhcps_start(struct ip_info *info, netif* apnetif)
|
||||
{
|
||||
// apnetif is esp interface, replaced by lwip2's
|
||||
// netif_git[SOFTAP_IF] interface in constructor
|
||||
(void)apnetif;
|
||||
|
||||
#if 0
|
||||
// can't use C++ now, global ctors are not initialized yet
|
||||
dhcpSoftAP.begin(info);
|
||||
#else
|
||||
(void)info;
|
||||
// initial version: emulate nonos-sdk in DhcpServer class before
|
||||
// trying to change legacy behavor
|
||||
// `fw_has_started_softap_dhcps` will be read in DhcpServer::DhcpServer
|
||||
// which is called when c++ ctors are initialized, specifically
|
||||
// dhcpSoftAP intialized with AP interface number above.
|
||||
fw_has_started_softap_dhcps = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dhcps_stop()
|
||||
{
|
||||
dhcpSoftAP.end();
|
||||
}
|
||||
|
||||
} // extern "C"
|
1613
cores/esp8266/LwipDhcpServer.cpp
Normal file
1613
cores/esp8266/LwipDhcpServer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
124
cores/esp8266/LwipDhcpServer.h
Normal file
124
cores/esp8266/LwipDhcpServer.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
lwIPDhcpServer.h - DHCP server
|
||||
|
||||
Copyright (c) 2016 Espressif. All rights reserved.
|
||||
Copyright (c) 2020 esp8266 arduino. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
// original sources (no license provided)
|
||||
// ESP8266_NONOS_SDK/third_party/lwip/app/dhcpserver.c
|
||||
// ESP8266_NONOS_SDK/third_party/include/lwip/app/dhcpserver.h
|
||||
*/
|
||||
|
||||
// lwIPDhcpServer.{cc,h} encapsulate original nonos-sdk dhcp server
|
||||
// nearly as-is. This is an initial version to guaranty legacy behavior
|
||||
// with same default values.
|
||||
|
||||
#ifndef __DHCPS_H__
|
||||
#define __DHCPS_H__
|
||||
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
|
||||
class DhcpServer
|
||||
{
|
||||
public:
|
||||
|
||||
DhcpServer(netif* netif);
|
||||
~DhcpServer();
|
||||
|
||||
void setDns(int num, const ipv4_addr_t* dns);
|
||||
|
||||
bool begin(ip_info* info);
|
||||
void end();
|
||||
bool isRunning();
|
||||
|
||||
// this is the C interface encapsulated in a class
|
||||
// (originally dhcpserver.c in lwIP-v1.4 in NonOS-SDK)
|
||||
// (not changing everything at once)
|
||||
// the API below is subject to change
|
||||
|
||||
// legacy public C structure and API to eventually turn into C++
|
||||
|
||||
void init_dhcps_lease(uint32 ip);
|
||||
bool set_dhcps_lease(struct dhcps_lease *please);
|
||||
bool get_dhcps_lease(struct dhcps_lease *please);
|
||||
bool set_dhcps_offer_option(uint8 level, void* optarg);
|
||||
bool set_dhcps_lease_time(uint32 minute);
|
||||
bool reset_dhcps_lease_time(void);
|
||||
uint32 get_dhcps_lease_time(void);
|
||||
bool add_dhcps_lease(uint8 *macaddr);
|
||||
|
||||
void dhcps_set_dns(int num, const ipv4_addr_t* dns);
|
||||
|
||||
protected:
|
||||
|
||||
// legacy C structure and API to eventually turn into C++
|
||||
|
||||
typedef struct _list_node
|
||||
{
|
||||
void *pnode;
|
||||
struct _list_node *pnext;
|
||||
} list_node;
|
||||
|
||||
void node_insert_to_list(list_node **phead, list_node* pinsert);
|
||||
void node_remove_from_list(list_node **phead, list_node* pdelete);
|
||||
uint8_t* add_msg_type(uint8_t *optptr, uint8_t type);
|
||||
uint8_t* add_offer_options(uint8_t *optptr);
|
||||
uint8_t* add_end(uint8_t *optptr);
|
||||
void create_msg(struct dhcps_msg *m);
|
||||
void send_offer(struct dhcps_msg *m);
|
||||
void send_nak(struct dhcps_msg *m);
|
||||
void send_ack(struct dhcps_msg *m);
|
||||
uint8_t parse_options(uint8_t *optptr, sint16_t len);
|
||||
sint16_t parse_msg(struct dhcps_msg *m, u16_t len);
|
||||
static void S_handle_dhcp(void *arg,
|
||||
struct udp_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
const ip_addr_t *addr,
|
||||
uint16_t port);
|
||||
void handle_dhcp(
|
||||
struct udp_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
const ip_addr_t *addr,
|
||||
uint16_t port);
|
||||
void kill_oldest_dhcps_pool(void);
|
||||
void dhcps_coarse_tmr(void); // CURRENTLY NOT CALLED
|
||||
void dhcps_client_leave(u8 *bssid, struct ipv4_addr *ip, bool force);
|
||||
uint32 dhcps_client_update(u8 *bssid, struct ipv4_addr *ip);
|
||||
|
||||
netif* _netif;
|
||||
|
||||
struct udp_pcb *pcb_dhcps;
|
||||
ip_addr_t broadcast_dhcps;
|
||||
struct ipv4_addr server_address;
|
||||
struct ipv4_addr client_address;
|
||||
struct ipv4_addr dns_address;
|
||||
uint32 dhcps_lease_time;
|
||||
|
||||
struct dhcps_lease dhcps_lease;
|
||||
list_node *plist;
|
||||
uint8 offer;
|
||||
bool renew;
|
||||
|
||||
static const uint32 magic_cookie;
|
||||
};
|
||||
|
||||
// SoftAP DHCP server always exists and is started on boot
|
||||
extern DhcpServer dhcpSoftAP;
|
||||
extern "C" int fw_has_started_softap_dhcps;
|
||||
|
||||
#endif // __DHCPS_H__
|
156
cores/esp8266/LwipIntf.cpp
Normal file
156
cores/esp8266/LwipIntf.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
|
||||
extern "C" {
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#if LWIP_IPV6
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#endif
|
||||
|
||||
#include <user_interface.h>
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
#include "LwipIntf.h"
|
||||
|
||||
// args | esp order arduino order
|
||||
// ---- + --------- -------------
|
||||
// local_ip | local_ip local_ip
|
||||
// arg1 | gateway dns1
|
||||
// arg2 | netmask gateway
|
||||
// arg3 | dns1 netmask
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
|
||||
bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3,
|
||||
IPAddress& gateway, IPAddress& netmask, IPAddress& dns1)
|
||||
{
|
||||
//To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order, otherwise Arduino order.
|
||||
gateway = arg1;
|
||||
netmask = arg2;
|
||||
dns1 = arg3;
|
||||
|
||||
if (netmask[0] != 255)
|
||||
{
|
||||
//octet is not 255 => interpret as Arduino order
|
||||
gateway = arg2;
|
||||
netmask = arg3[0] == 0 ? IPAddress(255, 255, 255, 0) : arg3; //arg order is arduino and 4th arg not given => assign it arduino default
|
||||
dns1 = arg1;
|
||||
}
|
||||
|
||||
// check whether all is IPv4 (or gateway not set)
|
||||
if (!(local_ip.isV4() && netmask.isV4() && (!gateway.isSet() || gateway.isV4())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//ip and gateway must be in the same netmask
|
||||
if (gateway.isSet() && (local_ip.v4() & netmask.v4()) != (gateway.v4() & netmask.v4()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Get ESP8266 station DHCP hostname
|
||||
@return hostname
|
||||
*/
|
||||
String LwipIntf::hostname(void)
|
||||
{
|
||||
return wifi_station_get_hostname();
|
||||
}
|
||||
|
||||
/**
|
||||
Set ESP8266 station DHCP hostname
|
||||
@param aHostname max length:24
|
||||
@return ok
|
||||
*/
|
||||
bool LwipIntf::hostname(const char* aHostname)
|
||||
{
|
||||
/*
|
||||
vvvv RFC952 vvvv
|
||||
ASSUMPTIONS
|
||||
1. A "name" (Net, Host, Gateway, or Domain name) is a text string up
|
||||
to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus
|
||||
sign (-), and period (.). Note that periods are only allowed when
|
||||
they serve to delimit components of "domain style names". (See
|
||||
RFC-921, "Domain Name System Implementation Schedule", for
|
||||
background). No blank or space characters are permitted as part of a
|
||||
name. No distinction is made between upper and lower case. The first
|
||||
character must be an alpha character. The last character must not be
|
||||
a minus sign or period. A host which serves as a GATEWAY should have
|
||||
"-GATEWAY" or "-GW" as part of its name. Hosts which do not serve as
|
||||
Internet gateways should not use "-GATEWAY" and "-GW" as part of
|
||||
their names. A host which is a TAC should have "-TAC" as the last
|
||||
part of its host name, if it is a DoD host. Single character names
|
||||
or nicknames are not allowed.
|
||||
^^^^ RFC952 ^^^^
|
||||
|
||||
- 24 chars max
|
||||
- only a..z A..Z 0..9 '-'
|
||||
- no '-' as last char
|
||||
*/
|
||||
|
||||
size_t len = strlen(aHostname);
|
||||
|
||||
if (len == 0 || len > 32)
|
||||
{
|
||||
// nonos-sdk limit is 32
|
||||
// (dhcp hostname option minimum size is ~60)
|
||||
DEBUGV("WiFi.(set)hostname(): empty or large(>32) name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check RFC compliance
|
||||
bool compliant = (len <= 24);
|
||||
for (size_t i = 0; compliant && i < len; i++)
|
||||
if (!isalnum(aHostname[i]) && aHostname[i] != '-')
|
||||
{
|
||||
compliant = false;
|
||||
}
|
||||
if (aHostname[len - 1] == '-')
|
||||
{
|
||||
compliant = false;
|
||||
}
|
||||
|
||||
if (!compliant)
|
||||
{
|
||||
DEBUGV("hostname '%s' is not compliant with RFC952\n", aHostname);
|
||||
}
|
||||
|
||||
bool ret = wifi_station_set_hostname(aHostname);
|
||||
if (!ret)
|
||||
{
|
||||
DEBUGV("WiFi.hostname(%s): wifi_station_set_hostname() failed\n", aHostname);
|
||||
return false;
|
||||
}
|
||||
|
||||
// now we should inform dhcp server for this change, using lwip_renew()
|
||||
// looping through all existing interface
|
||||
// harmless for AP, also compatible with ethernet adapters (to come)
|
||||
for (netif* intf = netif_list; intf; intf = intf->next)
|
||||
{
|
||||
|
||||
// unconditionally update all known interfaces
|
||||
intf->hostname = wifi_station_get_hostname();
|
||||
|
||||
if (netif_dhcp_data(intf) != nullptr)
|
||||
{
|
||||
// renew already started DHCP leases
|
||||
err_t lwipret = dhcp_renew(intf);
|
||||
if (lwipret != ERR_OK)
|
||||
{
|
||||
DEBUGV("WiFi.hostname(%s): lwIP error %d on interface %c%c (index %d)\n",
|
||||
intf->hostname, (int)lwipret, intf->name[0], intf->name[1], intf->num);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret && compliant;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define _LWIPINTF_H
|
||||
|
||||
#include <lwip/netif.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@ -12,15 +13,31 @@ public:
|
||||
|
||||
using CBType = std::function <void(netif*)>;
|
||||
|
||||
static bool stateUpCB (LwipIntf::CBType&& cb);
|
||||
static bool stateUpCB(LwipIntf::CBType&& cb);
|
||||
|
||||
private:
|
||||
// reorder WiFi.config() parameters for a esp8266/official Arduino dual-compatibility API
|
||||
// args | esp order arduino order
|
||||
// ---- + --------- -------------
|
||||
// local_ip | local_ip local_ip
|
||||
// arg1 | gateway dns1
|
||||
// arg2 | netmask [Agateway
|
||||
// arg3 | dns1 netmask
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
static
|
||||
bool ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3,
|
||||
IPAddress& gateway, IPAddress& netmask, IPAddress& dns1);
|
||||
|
||||
LwipIntf () { } // private, cannot be directly allocated
|
||||
String hostname();
|
||||
bool hostname(const String& aHostname)
|
||||
{
|
||||
return hostname(aHostname.c_str());
|
||||
}
|
||||
bool hostname(const char* aHostname);
|
||||
|
||||
protected:
|
||||
|
||||
static bool stateChangeSysCB (LwipIntf::CBType&& cb);
|
||||
static bool stateChangeSysCB(LwipIntf::CBType&& cb);
|
||||
};
|
||||
|
||||
#endif // _LWIPINTF_H
|
||||
|
@ -8,14 +8,16 @@
|
||||
static int netifStatusChangeListLength = 0;
|
||||
LwipIntf::CBType netifStatusChangeList [NETIF_STATUS_CB_SIZE];
|
||||
|
||||
extern "C" void netif_status_changed (struct netif* netif)
|
||||
extern "C" void netif_status_changed(struct netif* netif)
|
||||
{
|
||||
// override the default empty weak function
|
||||
for (int i = 0; i < netifStatusChangeListLength; i++)
|
||||
{
|
||||
netifStatusChangeList[i](netif);
|
||||
}
|
||||
}
|
||||
|
||||
bool LwipIntf::stateChangeSysCB (LwipIntf::CBType&& cb)
|
||||
bool LwipIntf::stateChangeSysCB(LwipIntf::CBType&& cb)
|
||||
{
|
||||
if (netifStatusChangeListLength >= NETIF_STATUS_CB_SIZE)
|
||||
{
|
||||
@ -29,14 +31,14 @@ bool LwipIntf::stateChangeSysCB (LwipIntf::CBType&& cb)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LwipIntf::stateUpCB (LwipIntf::CBType&& cb)
|
||||
bool LwipIntf::stateUpCB(LwipIntf::CBType&& cb)
|
||||
{
|
||||
return stateChangeSysCB([cb](netif* nif)
|
||||
return stateChangeSysCB([cb](netif * nif)
|
||||
{
|
||||
if (netif_is_up(nif))
|
||||
schedule_function([cb, nif]()
|
||||
{
|
||||
cb(nif);
|
||||
});
|
||||
{
|
||||
cb(nif);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
386
cores/esp8266/LwipIntfDev.h
Normal file
386
cores/esp8266/LwipIntfDev.h
Normal file
@ -0,0 +1,386 @@
|
||||
|
||||
#ifndef _LWIPINTFDEV_H
|
||||
#define _LWIPINTFDEV_H
|
||||
|
||||
// TODO:
|
||||
// remove all Serial.print
|
||||
// unchain pbufs
|
||||
|
||||
#include <netif/ethernet.h>
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/etharp.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/apps/sntp.h>
|
||||
|
||||
#include <user_interface.h> // wifi_get_macaddr()
|
||||
|
||||
#include "SPI.h"
|
||||
#include "Schedule.h"
|
||||
#include "LwipIntf.h"
|
||||
#include "wl_definitions.h"
|
||||
|
||||
#ifndef DEFAULT_MTU
|
||||
#define DEFAULT_MTU 1500
|
||||
#endif
|
||||
|
||||
template <class RawDev>
|
||||
class LwipIntfDev: public LwipIntf, public RawDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
LwipIntfDev(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1):
|
||||
RawDev(cs, spi, intr),
|
||||
_mtu(DEFAULT_MTU),
|
||||
_intrPin(intr),
|
||||
_started(false),
|
||||
_default(false)
|
||||
{
|
||||
memset(&_netif, 0, sizeof(_netif));
|
||||
}
|
||||
|
||||
boolean config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3, const IPAddress& dns2);
|
||||
|
||||
// default mac-address is inferred from esp8266's STA interface
|
||||
boolean begin(const uint8_t *macAddress = nullptr, const uint16_t mtu = DEFAULT_MTU);
|
||||
|
||||
const netif* getNetIf() const
|
||||
{
|
||||
return &_netif;
|
||||
}
|
||||
|
||||
IPAddress localIP() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)));
|
||||
}
|
||||
IPAddress subnetMask() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.netmask)));
|
||||
}
|
||||
IPAddress gatewayIP() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.gw)));
|
||||
}
|
||||
|
||||
void setDefault();
|
||||
|
||||
bool connected()
|
||||
{
|
||||
return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr));
|
||||
}
|
||||
|
||||
// ESP8266WiFi API compatibility
|
||||
|
||||
wl_status_t status();
|
||||
|
||||
protected:
|
||||
|
||||
err_t netif_init();
|
||||
void netif_status_callback();
|
||||
|
||||
static err_t netif_init_s(netif* netif);
|
||||
static err_t linkoutput_s(netif *netif, struct pbuf *p);
|
||||
static void netif_status_callback_s(netif* netif);
|
||||
|
||||
// called on a regular basis or on interrupt
|
||||
err_t handlePackets();
|
||||
|
||||
// members
|
||||
|
||||
netif _netif;
|
||||
|
||||
uint16_t _mtu;
|
||||
int8_t _intrPin;
|
||||
uint8_t _macAddress[6];
|
||||
bool _started;
|
||||
bool _default;
|
||||
|
||||
};
|
||||
|
||||
template <class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2)
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
DEBUGV("LwipIntfDev: use config() then begin()\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
IPAddress realGateway, realNetmask, realDns1;
|
||||
if (!ipAddressReorder(localIP, gateway, netmask, dns1, realGateway, realNetmask, realDns1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ip4_addr_set_u32(ip_2_ip4(&_netif.ip_addr), localIP.v4());
|
||||
ip4_addr_set_u32(ip_2_ip4(&_netif.gw), realGateway.v4());
|
||||
ip4_addr_set_u32(ip_2_ip4(&_netif.netmask), realNetmask.v4());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu)
|
||||
{
|
||||
if (mtu)
|
||||
{
|
||||
_mtu = mtu;
|
||||
}
|
||||
|
||||
if (macAddress)
|
||||
{
|
||||
memcpy(_macAddress, macAddress, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
_netif.num = 2;
|
||||
for (auto n = netif_list; n; n = n->next)
|
||||
if (n->num >= _netif.num)
|
||||
{
|
||||
_netif.num = n->num + 1;
|
||||
}
|
||||
|
||||
#if 1
|
||||
// forge a new mac-address from the esp's wifi sta one
|
||||
// I understand this is cheating with an official mac-address
|
||||
wifi_get_macaddr(STATION_IF, (uint8*)_macAddress);
|
||||
#else
|
||||
// https://serverfault.com/questions/40712/what-range-of-mac-addresses-can-i-safely-use-for-my-virtual-machines
|
||||
memset(_macAddress, 0, 6);
|
||||
_macAddress[0] = 0xEE;
|
||||
#endif
|
||||
_macAddress[3] += _netif.num; // alter base mac address
|
||||
_macAddress[0] &= 0xfe; // set as locally administered, unicast, per
|
||||
_macAddress[0] |= 0x02; // https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
|
||||
}
|
||||
|
||||
if (!RawDev::begin(_macAddress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// setup lwIP netif
|
||||
|
||||
_netif.hwaddr_len = sizeof _macAddress;
|
||||
memcpy(_netif.hwaddr, _macAddress, sizeof _macAddress);
|
||||
|
||||
// due to netif_add() api: ...
|
||||
ip_addr_t ip_addr, netmask, gw;
|
||||
ip_addr_copy(ip_addr, _netif.ip_addr);
|
||||
ip_addr_copy(netmask, _netif.netmask);
|
||||
ip_addr_copy(gw, _netif.gw);
|
||||
|
||||
if (!netif_add(&_netif, ip_2_ip4(&ip_addr), ip_2_ip4(&netmask), ip_2_ip4(&gw), this, netif_init_s, ethernet_input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_netif.flags |= NETIF_FLAG_UP;
|
||||
|
||||
if (localIP().v4() == 0)
|
||||
{
|
||||
switch (dhcp_start(&_netif))
|
||||
{
|
||||
case ERR_OK:
|
||||
break;
|
||||
|
||||
case ERR_IF:
|
||||
return false;
|
||||
|
||||
default:
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_started = true;
|
||||
|
||||
if (_intrPin >= 0)
|
||||
{
|
||||
if (RawDev::interruptIsPossible())
|
||||
{
|
||||
//attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
}
|
||||
else
|
||||
{
|
||||
::printf((PGM_P)F("lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
_intrPin = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_intrPin < 0 && !schedule_recurrent_function_us([&]()
|
||||
{
|
||||
this->handlePackets();
|
||||
return true;
|
||||
}, 100))
|
||||
{
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
wl_status_t LwipIntfDev<RawDev>::status()
|
||||
{
|
||||
return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif *netif, struct pbuf *pbuf)
|
||||
{
|
||||
LwipIntfDev* ths = (LwipIntfDev*)netif->state;
|
||||
|
||||
if (pbuf->len != pbuf->tot_len || pbuf->next)
|
||||
{
|
||||
Serial.println("ERRTOT\r\n");
|
||||
}
|
||||
|
||||
uint16_t len = ths->sendFrame((const uint8_t*)pbuf->payload, pbuf->len);
|
||||
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture)
|
||||
{
|
||||
phy_capture(ths->_netif.num, (const char*)pbuf->payload, pbuf->len, /*out*/1, /*success*/len == pbuf->len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return len == pbuf->len ? ERR_OK : ERR_MEM;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init_s(struct netif* netif)
|
||||
{
|
||||
return ((LwipIntfDev*)netif->state)->netif_init();
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback_s(struct netif* netif)
|
||||
{
|
||||
((LwipIntfDev*)netif->state)->netif_status_callback();
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init()
|
||||
{
|
||||
_netif.name[0] = 'e';
|
||||
_netif.name[1] = '0' + _netif.num;
|
||||
_netif.mtu = _mtu;
|
||||
_netif.chksum_flags = NETIF_CHECKSUM_ENABLE_ALL;
|
||||
_netif.flags =
|
||||
NETIF_FLAG_ETHARP
|
||||
| NETIF_FLAG_IGMP
|
||||
| NETIF_FLAG_BROADCAST
|
||||
| NETIF_FLAG_LINK_UP;
|
||||
|
||||
// lwIP's doc: This function typically first resolves the hardware
|
||||
// address, then sends the packet. For ethernet physical layer, this is
|
||||
// usually lwIP's etharp_output()
|
||||
_netif.output = etharp_output;
|
||||
|
||||
// lwIP's doc: This function outputs the pbuf as-is on the link medium
|
||||
// (this must points to the raw ethernet driver, meaning: us)
|
||||
_netif.linkoutput = linkoutput_s;
|
||||
|
||||
_netif.status_callback = netif_status_callback_s;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback()
|
||||
{
|
||||
if (connected())
|
||||
{
|
||||
if (_default)
|
||||
{
|
||||
netif_set_default(&_netif);
|
||||
}
|
||||
sntp_stop();
|
||||
sntp_init();
|
||||
}
|
||||
else if (netif_default == &_netif)
|
||||
{
|
||||
netif_set_default(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
{
|
||||
int pkt = 0;
|
||||
while (1)
|
||||
{
|
||||
if (++pkt == 10)
|
||||
// prevent starvation
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
uint16_t tot_len = RawDev::readFrameSize();
|
||||
if (!tot_len)
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
// from doc: use PBUF_RAM for TX, PBUF_POOL from RX
|
||||
// however:
|
||||
// PBUF_POOL can return chained pbuf (not in one piece)
|
||||
// and WiznetDriver does not have the proper API to deal with that
|
||||
// so in the meantime, we use PBUF_RAM instead which is currently
|
||||
// guarantying to deliver a continuous chunk of memory.
|
||||
// TODO: tweak the wiznet driver to allow copying partial chunk
|
||||
// of received data and use PBUF_POOL.
|
||||
pbuf* pbuf = pbuf_alloc(PBUF_RAW, tot_len, PBUF_RAM);
|
||||
if (!pbuf || pbuf->len < tot_len)
|
||||
{
|
||||
if (pbuf)
|
||||
{
|
||||
pbuf_free(pbuf);
|
||||
}
|
||||
RawDev::discardFrame(tot_len);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
uint16_t len = RawDev::readFrameData((uint8_t*)pbuf->payload, tot_len);
|
||||
if (len != tot_len)
|
||||
{
|
||||
// tot_len is given by readFrameSize()
|
||||
// and is supposed to be honoured by readFrameData()
|
||||
// todo: ensure this test is unneeded, remove the print
|
||||
Serial.println("read error?\r\n");
|
||||
pbuf_free(pbuf);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
err_t err = _netif.input(pbuf, &_netif);
|
||||
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture)
|
||||
{
|
||||
phy_capture(_netif.num, (const char*)pbuf->payload, tot_len, /*out*/0, /*success*/err == ERR_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
pbuf_free(pbuf);
|
||||
return err;
|
||||
}
|
||||
// (else) allocated pbuf is now lwIP's responsibility
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
void LwipIntfDev<RawDev>::setDefault()
|
||||
{
|
||||
_default = true;
|
||||
if (connected())
|
||||
{
|
||||
netif_set_default(&_netif);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _LWIPINTFDEV_H
|
88
cores/esp8266/wl_definitions.h
Normal file
88
cores/esp8266/wl_definitions.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
wl_definitions.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* wl_definitions.h
|
||||
*
|
||||
* Created on: Mar 6, 2011
|
||||
* Author: dlafauci
|
||||
*/
|
||||
|
||||
#ifndef WL_DEFINITIONS_H_
|
||||
#define WL_DEFINITIONS_H_
|
||||
|
||||
// Maximum size of a SSID
|
||||
#define WL_SSID_MAX_LENGTH 32
|
||||
// Length of passphrase. Valid lengths are 8-63.
|
||||
#define WL_WPA_KEY_MAX_LENGTH 63
|
||||
// Length of key in bytes. Valid values are 5 and 13.
|
||||
#define WL_WEP_KEY_MAX_LENGTH 13
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_MAC_ADDR_LENGTH 6
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_IPV4_LENGTH 4
|
||||
// Maximum size of a SSID list
|
||||
#define WL_NETWORKS_LIST_MAXNUM 10
|
||||
// Maxmium number of socket
|
||||
#define MAX_SOCK_NUM 4
|
||||
// Socket not available constant
|
||||
#define SOCK_NOT_AVAIL 255
|
||||
// Default state value for Wifi state field
|
||||
#define NA_STATE -1
|
||||
//Maximum number of attempts to establish wifi connection
|
||||
#define WL_MAX_ATTEMPT_CONNECTION 10
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL = 1,
|
||||
WL_SCAN_COMPLETED = 2,
|
||||
WL_CONNECTED = 3,
|
||||
WL_CONNECT_FAILED = 4,
|
||||
WL_CONNECTION_LOST = 5,
|
||||
WL_WRONG_PASSWORD = 6,
|
||||
WL_DISCONNECTED = 7
|
||||
} wl_status_t;
|
||||
|
||||
/* Encryption modes */
|
||||
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
|
||||
ENC_TYPE_WEP = 5,
|
||||
ENC_TYPE_TKIP = 2,
|
||||
ENC_TYPE_CCMP = 4,
|
||||
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
|
||||
ENC_TYPE_NONE = 7,
|
||||
ENC_TYPE_AUTO = 8
|
||||
};
|
||||
|
||||
#if !defined(LWIP_INTERNAL) && !defined(__LWIP_TCP_H__) && !defined(LWIP_HDR_TCPBASE_H)
|
||||
enum wl_tcp_state {
|
||||
CLOSED = 0,
|
||||
LISTEN = 1,
|
||||
SYN_SENT = 2,
|
||||
SYN_RCVD = 3,
|
||||
ESTABLISHED = 4,
|
||||
FIN_WAIT_1 = 5,
|
||||
FIN_WAIT_2 = 6,
|
||||
CLOSE_WAIT = 7,
|
||||
CLOSING = 8,
|
||||
LAST_ACK = 9,
|
||||
TIME_WAIT = 10
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* WL_DEFINITIONS_H_ */
|
Reference in New Issue
Block a user