Skip to content
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

Implement USB NCM #37

Merged
merged 2 commits into from
Jan 6, 2024
Merged
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
3 changes: 2 additions & 1 deletion components/hardware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ idf_component_register(
SRCS
"src/manager.cc"
"src/net_eth.cc"
"src/net_usb.cc"
"src/net_wifi.cc"
"src/net.cc"
INCLUDE_DIRS
"include"
REQUIRES
esp_netif lilygo
PRIV_REQUIRES
driver esp_eth esp_wifi esp_timer nvs_flash
driver esp_eth esp_wifi esp_timer esp_tinyusb nvs_flash
)
21 changes: 11 additions & 10 deletions components/hardware/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,19 @@ menu "BoundBox Hardware"
default 15
depends on BBHW_HAS_ETH

config BBHW_HAS_WIFI
bool "Has WiFi"
default y

choice BBHW_NETKIND
prompt "Default network implementation"
default BBHW_NETKIND_ETH
prompt "Network implementation"
default BBHW_NETKIND_USB

config BBHW_NETKIND_ETH
bool "Ethernet"
depends on BBHW_HAS_ETH
config BBHW_NETKIND_USB
bool "USB"

config BBHW_NETKIND_WIFI_STA
bool "WiFi"
depends on BBHW_HAS_WIFI

config BBHW_NETKIND_ETH
bool "Ethernet"
depends on BBHW_HAS_ETH
endchoice

config BBHW_HOSTNAME
Expand All @@ -86,14 +84,17 @@ menu "BoundBox Hardware"

config BBHW_NET_IP
string "Static IP to use"
default "192.168.8.1"
depends on BBHW_NET_USE_STATIC_IP

config BBHW_NET_SUBNET
string "Static Subnet to use"
default "255.255.255.0"
depends on BBHW_NET_USE_STATIC_IP

config BBHW_NET_GW
string "Static Gateway to use"
default "0.0.0.0"
depends on BBHW_NET_USE_STATIC_IP

config BBHW_NET_DNS
Expand Down
4 changes: 4 additions & 0 deletions components/hardware/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dependencies:
espressif/esp_tinyusb: "^1.4.2"
idf: "^5.1.0"

4 changes: 2 additions & 2 deletions components/hardware/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#define BBHW_SPI_HOSTID NeedTooChooseSpiHost
#ifdef CONFIG_BBHW_USE_SPI2_HOST
#undef BBHW_SPI_HOSTID
#define BBHW_SPI_HOSTID SPI3_HOST
#define BBHW_SPI_HOSTID SPI2_HOST
#endif
#ifdef CONFIG_BBHW_USE_SPI3_HOST
#undef BBHW_SPI_HOSTID
#define BBHW_SPI_HOSTID SPI3_HOST
#endif
#endif
45 changes: 35 additions & 10 deletions components/hardware/src/net.cc
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#include "hardware/net.h"
#include "config.h"

#include "net_usb.h"
#include "net_wifi.h"
#if CONFIG_BBHW_HAS_ETH
#include "net_eth.h"
#endif
#if CONFIG_BBHW_HAS_WIFI
#include "net_wifi.h"
#endif

#include <esp_netif.h>
#include <esp_event.h>
Expand Down Expand Up @@ -38,13 +37,36 @@ namespace
netReady = true;
localIP = ip_info->ip;

ESP_LOGI(TAG, "%s IP Address", event_id == IP_EVENT_ETH_GOT_IP ? "Ethernet" : "WiFi");
switch (event_id) {
case IP_EVENT_ETH_GOT_IP:
ESP_LOGI(TAG, "Ethernet connected");
break;
case IP_EVENT_STA_GOT_IP:
ESP_LOGI(TAG, "Wifi connected");
break;
default:
ESP_LOGI(TAG, "Something connected");
}

ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "Mask: " IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "Gateway: " IPSTR, IP2STR(&ip_info->gw));

if (!ip4_addr_isany_val(ip_info->ip)) {
ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info->ip));
}

if (!ip4_addr_isany_val(ip_info->netmask)) {
ESP_LOGI(TAG, "Mask: " IPSTR, IP2STR(&ip_info->netmask));
}

if (!ip4_addr_isany_val(ip_info->gw)) {
ESP_LOGI(TAG, "Gateway: " IPSTR, IP2STR(&ip_info->gw));
}

ESP_LOGI(TAG, "~~~~~~~~~~~");
break;
case IP_EVENT_AP_STAIPASSIGNED:
ESP_LOGI(TAG, "New client connected");
ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info->ip));
default:
return;
}
Expand All @@ -53,7 +75,11 @@ namespace

esp_err_t Net::Initialize()
{
#if CONFIG_BBHW_NETKIND_ETH
#if CONFIG_BBHW_NETKIND_USB
impl = std::make_unique<NetUsb>();
ESP_RETURN_ON_ERROR(impl->Initialize(), TAG, "failed to initialize usb network");

#elif CONFIG_BBHW_NETKIND_ETH
impl = std::make_unique<NetEth>();
ESP_RETURN_ON_ERROR(impl->Initialize(), TAG, "failed to initialize ethernet network");

Expand All @@ -62,8 +88,7 @@ esp_err_t Net::Initialize()
ESP_RETURN_ON_ERROR(impl->Initialize(), TAG, "failed to initialize wifi network");

#else
ESP_LOGE(TAG, "no network configured");
return ESP_FAIL;
#error No network configured
#endif

ESP_RETURN_ON_ERROR(esp_netif_init(), TAG, "failed to initialize netif");
Expand Down
21 changes: 18 additions & 3 deletions components/hardware/src/net_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ namespace Hardware
#endif
}

inline void BuildIPInfo(esp_netif_ip_info_t *ip, bool force)
{
#if !CONFIG_BBHW_NET_USE_STATIC_IP
if (!force) {
// doesn't use static IP - nothing to do
return;
}
#else
assert(ip);

memset(ip, 0 , sizeof(esp_netif_ip_info_t));
ip->ip.addr = ipaddr_addr(CONFIG_BBHW_NET_IP);
ip->netmask.addr = ipaddr_addr(CONFIG_BBHW_NET_SUBNET);
ip->gw.addr = ipaddr_addr(CONFIG_BBHW_NET_GW);
#endif
}

inline void SetIPInfo(esp_netif_t *netif)
{
#if !CONFIG_BBHW_NET_USE_STATIC_IP
Expand All @@ -40,9 +57,7 @@ namespace Hardware

esp_netif_ip_info_t ip;
memset(&ip, 0 , sizeof(esp_netif_ip_info_t));
ip.ip.addr = ipaddr_addr(CONFIG_BBHW_NET_IP);
ip.netmask.addr = ipaddr_addr(CONFIG_BBHW_NET_SUBNET);
ip.gw.addr = ipaddr_addr(CONFIG_BBHW_NET_GW);
BuildIPInfo(&ip, false);
ESP_ERROR_CHECK(esp_netif_set_ip_info(netif, &ip));

SetDnsServer(netif, ESP_NETIF_DNS_MAIN);
Expand Down
10 changes: 2 additions & 8 deletions components/hardware/src/net_eth.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,8 @@ esp_err_t NetEth::Initialize()
.phy_addr = CONFIG_BBHW_ETH_PHY_ADDR,
};

// The SPI Ethernet module(s) might not have a burned factory MAC address, hence use manually configured address(es).
// In this example, Locally Administered MAC address derived from ESP32x base MAC address is used.
// Note that Locally Administered OUI range should be used only when testing on a LAN under your control!
uint8_t base_mac_addr[ETH_ADDR_LEN];
ESP_RETURN_ON_ERROR(esp_efuse_mac_get_default(base_mac_addr), TAG, "get EFUSE MAC failed");
uint8_t local_mac_1[ETH_ADDR_LEN];
esp_derive_local_mac(local_mac_1, base_mac_addr);
spi_eth_module_config.mac_addr = local_mac_1;
esp_err_t err = esp_read_mac(spi_eth_module_config.mac_addr, ESP_MAC_WIFI_STA);
ESP_RETURN_ON_ERROR(err, TAG, "read sta mac");

ethHandle = ethInitSpi(spi_eth_module_config, nullptr, nullptr);
ESP_RETURN_ON_FALSE(ethHandle, ESP_FAIL, TAG, "SPI Ethernet init failed");
Expand Down
6 changes: 1 addition & 5 deletions components/hardware/src/net_eth.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,14 @@ namespace Hardware

~NetEth()
{
if (netif != nullptr) {
esp_eth_stop(netif);
}

if (ethHandle != nullptr) {
esp_eth_stop(ethHandle);
esp_eth_driver_uninstall(ethHandle);
}
}

private:
esp_eth_handle_t ethHandle = nullptr;
esp_netif_inherent_config_t netifCfg;
esp_netif_t* netif;
};
}
133 changes: 133 additions & 0 deletions components/hardware/src/net_usb.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "config.h"
#include "net_usb.h"
#include "net_common.h"

#include <assert.h>

#include <tinyusb.h>
#include <tinyusb_net.h>

#include <esp_netif.h>
#include <esp_eth.h>
#include <esp_eth_driver.h>
#include <esp_mac.h>
#include <esp_log.h>
#include <esp_check.h>
#include <esp_event.h>


using namespace Hardware;

namespace
{
static const char* TAG = "hardware::net::usb";

esp_err_t wired_send(void *buffer, uint16_t len, void *buff_free_arg)
{
return tinyusb_net_send_sync(buffer, len, buff_free_arg, pdMS_TO_TICKS(100));
}

static void l2_free(void *h, void *buffer)
{
free(buffer);
}

static esp_err_t netif_transmit (void *h, void *buffer, size_t len)
{
if (wired_send(buffer, len, NULL) != ESP_OK) {
ESP_LOGE(TAG, "Failed to send buffer to USB!");
}
return ESP_OK;
}

esp_err_t netif_recv_callback(void *buffer, uint16_t len, void *ctx)
{
esp_netif_t* netif = reinterpret_cast<esp_netif_t *>(ctx);
if (!netif) {
return ESP_OK;
}

void *buf_copy = malloc(len);
if (!buf_copy) {
return ESP_ERR_NO_MEM;
}
memcpy(buf_copy, buffer, len);
return esp_netif_receive(netif, buf_copy, len, NULL);
}
}

esp_err_t NetUsb::Initialize()
{
const tinyusb_config_t usbCfg = {
.external_phy = false,
};
esp_err_t err = tinyusb_driver_install(&usbCfg);
ESP_RETURN_ON_ERROR(err, TAG, "install TinyUSB driver");

BuildIPInfo(&this->ipInfo, true);
this->netifCfg = {
.flags = static_cast<esp_netif_flags_t>(ESP_NETIF_DHCP_SERVER | ESP_NETIF_FLAG_AUTOUP | ESP_NETIF_FLAG_EVENT_IP_MODIFIED),
.ip_info = &this->ipInfo,
.get_ip_event = IP_EVENT_ETH_GOT_IP,
.lost_ip_event = IP_EVENT_ETH_LOST_IP,
.if_key = "wired",
.if_desc = "usb ncm config device",
};
PatchNetifCfg(this->netifCfg);

this->driverCfg = {
.handle = (void *)1, // not using an instance, USB-NCM is a static singleton (must be != NULL)
.transmit = netif_transmit, // point to static Tx function
.driver_free_rx_buffer = l2_free // point to Free Rx buffer function
};

this->stackCfg = {
.lwip = {
.init_fn = ethernetif_init,
.input_fn = ethernetif_input
}
};

return ESP_OK;
}

esp_netif_config_t NetUsb::NetifConfig() const
{
return {
.base = &netifCfg,
.driver = &driverCfg,
.stack = &stackCfg,
};
}

esp_err_t NetUsb::Attach(esp_netif_t* netif)
{
assert(netif);

tinyusb_net_config_t netCfg = {
.on_recv_callback = netif_recv_callback,
.user_context = netif,
};

esp_err_t err = esp_read_mac(netCfg.mac_addr, ESP_MAC_WIFI_SOFTAP);
ESP_RETURN_ON_ERROR(err, TAG, "read softap mac");

err = tinyusb_net_init(TINYUSB_USBDEV_0, &netCfg);
ESP_RETURN_ON_ERROR(err, TAG, "initialize USB Net device");

err = esp_netif_set_mac(netif, netCfg.mac_addr);
ESP_RETURN_ON_ERROR(err, TAG, "set netif mac");

// start the interface manually (as the driver has been started already)
esp_netif_action_start(netif, 0, 0, 0);

// TODO(buglloc): do smth better plz
ip_event_got_ip_t evt = {
.esp_netif = netif,
.ip_changed = true,
};
BuildIPInfo(&evt.ip_info, true);
esp_event_post(IP_EVENT, IP_EVENT_ETH_GOT_IP, &evt, sizeof(evt), 0);

return ESP_OK;
}
Loading
Loading