Skip to content

Ethernet library: add missing functions #160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: arduino
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions libraries/SocketWrapper/Ethernet.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,80 @@
#include "Ethernet.h"

#if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy)

int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) {
setMACAddress(mac);
return NetworkInterface::begin(true, 0);
}

int EthernetClass::begin(uint8_t *mac, IPAddress ip) {
IPAddress dns = ip;
dns[3] = 1;

auto ret = begin(mac, ip, dns);
return ret;
}

int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) {
IPAddress gateway = ip;
gateway[3] = 1;

auto ret = begin(mac, ip, dns, gateway);
return ret;
}

int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) {
IPAddress subnet(255, 255, 255, 0);
auto ret = begin(mac, ip, dns, gateway, subnet);
return ret;
}

int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet, unsigned long timeout, unsigned long responseTimeout) {
setMACAddress(mac);

if (!NetworkInterface::setLocalIP(ip, subnet, gateway)) {
return 0;
}

if (!net_if_is_up(netif)) {
net_if_up(netif);
}

return 1;
}

EthernetLinkStatus EthernetClass::linkStatus() {
if ((hardwareStatus() == EthernetOk) && net_if_is_up(netif)) {
return LinkON;
}
return LinkOFF;
}

EthernetHardwareStatus EthernetClass::hardwareStatus() {
const struct device *const dev = DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(ethernet_phy));
if (device_is_ready(dev)) {
for (int i = 1; i < 3; i++) {
auto _if = net_if_get_by_index(i);
if (!net_eth_type_is_wifi(_if)) {
netif = _if;
break;
}
}
return EthernetOk;
} else {
return EthernetNoHardware;
}
}

void EthernetClass::setMACAddress(const uint8_t *mac_address) {
if (mac_address != nullptr) {
NetworkInterface::setMACAddress(mac_address);
}
}

IPAddress EthernetClass::localIP() {
return NetworkInterface::localIP();
}

EthernetClass Ethernet;
#endif
63 changes: 26 additions & 37 deletions libraries/SocketWrapper/Ethernet.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,44 +21,33 @@ class EthernetClass: public NetworkInterface
EthernetClass() {}
virtual ~EthernetClass() {}

EthernetLinkStatus linkStatus() {
hardwareStatus();
if (net_if_is_up(netif)) {
return LinkON;
} else {
return LinkOFF;
}
}

bool begin(bool blocking = true, uint32_t additional_event_mask = 0) {
hardwareStatus();
return NetworkInterface::begin(blocking, additional_event_mask);
}

bool begin(uint8_t* mac_address, int _timeout, int _response_timeout) {
return begin();
}

bool begin(uint8_t* mac_address, IPAddress _ip, IPAddress _dns, IPAddress _gateway, IPAddress _netmask, int _timeout, int _response_timeout) {
return begin();
}

EthernetHardwareStatus hardwareStatus() {
const struct device *const dev = DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(ethernet_phy));
if (device_is_ready(dev)) {
for (int i = 1; i < 3; i++) {
auto _if = net_if_get_by_index(i);
if (!net_eth_type_is_wifi(_if)) {
netif = _if;
break;
}
}
return EthernetOk;
} else {
return EthernetNoHardware;
}
}
int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
int maintain();
EthernetLinkStatus linkStatus();
EthernetHardwareStatus hardwareStatus();

// Manual configuration
int begin(uint8_t *mac, IPAddress ip);
int begin(uint8_t *mac, IPAddress ip, IPAddress dns);
int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway);
int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
void init(uint8_t sspin = 10);

void MACAddress(uint8_t *mac_address);
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsServerIP();

void setMACAddress(const uint8_t *mac_address);
void setLocalIP(const IPAddress local_ip);
void setSubnetMask(const IPAddress subnet);
void setGatewayIP(const IPAddress gateway);
void setDnsServerIP(const IPAddress dns_server);
void setRetransmissionTimeout(uint16_t milliseconds);
void setRetransmissionCount(uint8_t num);
};

extern EthernetClass Ethernet;

#endif
172 changes: 172 additions & 0 deletions libraries/SocketWrapper/SocketHelpers.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,176 @@
#include "SocketHelpers.h"

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(sketch, CONFIG_LOG_DEFAULT_LEVEL);

struct net_mgmt_event_callback NetworkInterface::mgmt_cb;
struct net_dhcpv4_option_callback NetworkInterface::dhcp_cb;

void NetworkInterface::event_handler(struct net_mgmt_event_callback *cb,
uint64_t mgmt_event,
struct net_if *iface)
{
int i = 0;

if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
return;
}

for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
char buf[NET_IPV4_ADDR_LEN];

if (iface->config.ip.ipv4->unicast[i].ipv4.addr_type !=
NET_ADDR_DHCP) {
continue;
}

LOG_INF(" Address[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->unicast[i].ipv4.address.in_addr,
buf, sizeof(buf)));
LOG_INF(" Subnet[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->unicast[i].netmask,
buf, sizeof(buf)));
LOG_INF(" Router[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->gw,
buf, sizeof(buf)));
LOG_INF("Lease time[%d]: %u seconds", net_if_get_by_iface(iface),
iface->config.dhcpv4.lease_time);
}
}

void NetworkInterface::option_handler(struct net_dhcpv4_option_callback *cb,
size_t length,
enum net_dhcpv4_msg_type msg_type,
struct net_if *iface)
{
char buf[NET_IPV4_ADDR_LEN];

LOG_INF("DHCP Option %d: %s", cb->option,
net_addr_ntop(AF_INET, cb->data, buf, sizeof(buf)));
}

int NetworkInterface::dhcp()
{
net_mgmt_init_event_callback(&mgmt_cb, event_handler, NET_EVENT_IPV4_ADDR_ADD | NET_EVENT_IF_UP | NET_EVENT_IF_DOWN);
net_mgmt_add_event_callback(&mgmt_cb);

net_dhcpv4_init_option_callback(&dhcp_cb, option_handler,
DHCP_OPTION_NTP, ntp_server,
sizeof(ntp_server));

net_dhcpv4_add_option_callback(&dhcp_cb);

net_dhcpv4_start(netif);

LOG_INF("DHCPv4 started...\n");

return 0;
}

void NetworkInterface::enable_dhcpv4_server(struct net_if *netif, char* _netmask)
{
static struct in_addr addr;
static struct in_addr netmaskAddr;

if (net_addr_pton(AF_INET, String(localIP()).c_str(), &addr)) {
LOG_ERR("Invalid address: %s", String(localIP()).c_str());
return;
}

if (net_addr_pton(AF_INET, _netmask, &netmaskAddr)) {
LOG_ERR("Invalid netmask: %s", _netmask);
return;
}

net_if_ipv4_set_gw(netif, &addr);

if (net_if_ipv4_addr_add(netif, &addr, NET_ADDR_MANUAL, 0) == NULL) {
LOG_ERR("unable to set IP address for AP interface");
}

if (!net_if_ipv4_set_netmask_by_addr(netif, &addr, &netmaskAddr)) {
LOG_ERR("Unable to set netmask for AP interface: %s", _netmask);
}

addr.s4_addr[3] += 10; /* Starting IPv4 address for DHCPv4 address pool. */

if (net_dhcpv4_server_start(netif, &addr) != 0) {
LOG_ERR("DHCP server is not started for desired IP");
return;
}

LOG_INF("DHCPv4 server started...\n");
}

IPAddress NetworkInterface::localIP() {
return IPAddress(netif->config.ip.ipv4->unicast[0].ipv4.address.in_addr.s_addr);
}

IPAddress NetworkInterface::subnetMask() {
return IPAddress(netif->config.ip.ipv4->unicast[0].netmask.s_addr);
}
IPAddress NetworkInterface::gatewayIP() {
return IPAddress(netif->config.ip.ipv4->gw.s_addr);
}
IPAddress NetworkInterface::dnsServerIP() {
return arduino::INADDR_NONE;
}

IPAddress NetworkInterface::dnsIP(int n) {
//TODO
}

void NetworkInterface::setMACAddress(const uint8_t* mac) {
struct net_eth_addr new_mac;
struct ethernet_req_params params = { 0 };

memcpy(&params.mac_address, &new_mac, sizeof(struct net_eth_addr));

net_if_down(netif); // Ensure the interface is down before changing the MAC address

int ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, netif,
&params, sizeof(params));
if (ret != 0) {
LOG_ERR("Failed to set MAC address via net_mgmt, ret=%d", ret);
} else {
LOG_INF("MAC address set successfully via net_mgmt");
}

net_if_up(netif); // Bring the interface back up after changing the MAC address
}

int NetworkInterface::begin(bool blocking, uint32_t additional_event_mask) {
dhcp();
int ret = net_mgmt_event_wait_on_iface(netif, NET_EVENT_IPV4_ADDR_ADD | additional_event_mask,
NULL, NULL, NULL, blocking ? K_FOREVER : K_SECONDS(1));
return (ret == 0) ? 1 : 0;
}

bool NetworkInterface::disconnect() {
return (net_if_down(netif) == 0);
}

bool NetworkInterface::setLocalIP(IPAddress ip, IPAddress subnet, IPAddress gateway) {
struct in_addr ip_addr, subnet_addr, gw_addr;

ip_addr.s_addr = ip;
subnet_addr.s_addr = subnet;
gw_addr.s_addr = gateway;

if (!net_if_ipv4_addr_add(netif, &ip_addr, NET_ADDR_MANUAL, 0)) {
LOG_ERR("Failed to set static IP address");
return false;
}

if (!net_if_ipv4_set_netmask_by_addr(netif, &ip_addr, &subnet_addr)) {
LOG_ERR("Failed to set subnet mask");
return false;
}

net_if_ipv4_set_gw(netif, &gw_addr);
LOG_INF("Static IP configured");
return true;
}
Loading