From 53b7904443109da0aa06e3225cddc0bcbdf85b93 Mon Sep 17 00:00:00 2001
From: Uros Majstorovic <majstor@majstor.org>
Date: Fri, 27 Aug 2021 02:34:46 +0200
Subject: added spi driver for imx8; added lwip tun driver

---
 fw/esp32/components/eos/app.c         | 225 ++++++++++++++++++++++++++++++++++
 fw/esp32/components/eos/cell_modem.c  |   2 +-
 fw/esp32/components/eos/cell_pcm.c    |   2 +-
 fw/esp32/components/eos/cell_ussd.c   |   2 +-
 fw/esp32/components/eos/include/app.h |  23 ++++
 fw/esp32/components/eos/include/eos.h |  14 ++-
 fw/esp32/components/eos/include/net.h |   3 +-
 fw/esp32/components/eos/include/tun.h |   1 +
 fw/esp32/components/eos/net.c         |  33 +++--
 fw/esp32/components/eos/power.c       |   1 -
 fw/esp32/components/eos/sock.c        |  13 +-
 fw/esp32/components/eos/tun.c         |  65 ++++++++++
 fw/esp32/components/eos/wifi.c        |   2 +-
 fw/esp32/main/app_main.c              |   8 +-
 14 files changed, 360 insertions(+), 34 deletions(-)
 create mode 100644 fw/esp32/components/eos/app.c
 create mode 100644 fw/esp32/components/eos/include/app.h
 create mode 100644 fw/esp32/components/eos/include/tun.h
 create mode 100644 fw/esp32/components/eos/tun.c

(limited to 'fw/esp32')

diff --git a/fw/esp32/components/eos/app.c b/fw/esp32/components/eos/app.c
new file mode 100644
index 0000000..5f8cc43
--- /dev/null
+++ b/fw/esp32/components/eos/app.c
@@ -0,0 +1,225 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <freertos/FreeRTOS.h>
+#include <freertos/semphr.h>
+#include <freertos/task.h>
+
+#include <esp_system.h>
+#include <esp_log.h>
+#include <esp_err.h>
+#include <esp_heap_caps.h>
+#include <driver/gpio.h>
+#include <driver/spi_slave.h>
+
+#include "eos.h"
+#include "msgq.h"
+#include "app.h"
+
+#define SPI_GPIO_CTS        26
+#define SPI_GPIO_RTS        27
+#define SPI_GPIO_MOSI       13
+#define SPI_GPIO_MISO       12
+#define SPI_GPIO_SCLK       14
+#define SPI_GPIO_CS         15
+
+#define SPI_SIZE_BUF        (EOS_APP_SIZE_BUF + 8)
+#define SPI_SIZE_HDR        3
+
+static EOSBufQ app_buf_q;
+static unsigned char *app_bufq_array[EOS_APP_SIZE_BUFQ];
+
+static EOSMsgQ app_send_q;
+static EOSMsgItem app_sndq_array[EOS_APP_SIZE_SNDQ];
+
+static SemaphoreHandle_t mutex;
+static SemaphoreHandle_t semaph;
+static TaskHandle_t app_xchg_task_handle;
+static const char *TAG = "EOS APP";
+
+static eos_app_fptr_t app_handler[EOS_APP_MAX_MTYPE];
+
+static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) {
+    ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len);
+}
+
+// Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high.
+static void _post_setup_cb(spi_slave_transaction_t *trans) {
+    gpio_set_level(SPI_GPIO_CTS, 1);
+}
+
+// Called after transaction is sent/received. We use this to set the handshake line low.
+static void _post_trans_cb(spi_slave_transaction_t *trans) {
+    gpio_set_level(SPI_GPIO_CTS, 0);
+}
+
+static void app_xchg_task(void *pvParameters) {
+    unsigned char mtype = 0;
+    unsigned char mtype_flags = 0;
+    unsigned char *buffer;
+    uint16_t len;
+    unsigned char *buf_send = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA);
+    unsigned char *buf_recv = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA);
+    esp_err_t ret;
+    size_t trans_len;
+
+    static spi_slave_transaction_t spi_tr;
+
+    //Configuration for the SPI bus
+    static spi_bus_config_t spi_bus_cfg = {
+        .mosi_io_num = SPI_GPIO_MOSI,
+        .miso_io_num = SPI_GPIO_MISO,
+        .sclk_io_num = SPI_GPIO_SCLK
+    };
+
+    //Configuration for the SPI slave interface
+    static spi_slave_interface_config_t spi_slave_cfg = {
+        .mode = 0,
+        .spics_io_num = SPI_GPIO_CS,
+        .queue_size = 2,
+        .flags = 0,
+        .post_setup_cb = _post_setup_cb,
+        .post_trans_cb = _post_trans_cb
+    };
+
+    //Initialize SPI slave interface
+    ret = spi_slave_initialize(HSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1);
+    assert(ret == ESP_OK);
+
+    memset(&spi_tr, 0, sizeof(spi_tr));
+    spi_tr.tx_buffer = buf_send;
+    spi_tr.rx_buffer = buf_recv;
+    spi_tr.length = SPI_SIZE_BUF * 8;
+
+    while (1) {
+        xSemaphoreTake(mutex, portMAX_DELAY);
+
+        eos_msgq_pop(&app_send_q, &mtype, &buffer, &len);
+        if (mtype) {
+            buf_send[0] = mtype;
+            buf_send[1] = len >> 8;
+            buf_send[2] = len & 0xFF;
+            if (buffer) {
+                memcpy(buf_send + SPI_SIZE_HDR, buffer, len);
+                eos_bufq_push(&app_buf_q, buffer);
+                xSemaphoreGive(semaph);
+            }
+        } else {
+            gpio_set_level(SPI_GPIO_RTS, 0);
+            buf_send[0] = 0;
+            buf_send[1] = 0;
+            buf_send[2] = 0;
+            len = 0;
+        }
+
+        xSemaphoreGive(mutex);
+
+        buf_recv[0] = 0;
+        buf_recv[1] = 0;
+        buf_recv[2] = 0;
+        spi_slave_transmit(HSPI_HOST, &spi_tr, portMAX_DELAY);
+
+        trans_len = spi_tr.trans_len / 8;
+        if (trans_len < SPI_SIZE_HDR) continue;
+
+        if (len + SPI_SIZE_HDR > trans_len) {
+            spi_tr.tx_buffer = buf_send + trans_len;
+            spi_tr.rx_buffer = buf_recv + trans_len;
+            spi_tr.length = (SPI_SIZE_BUF - trans_len) * 8;
+            spi_slave_transmit(HSPI_HOST, &spi_tr, portMAX_DELAY);
+            spi_tr.tx_buffer = buf_send;
+            spi_tr.rx_buffer = buf_recv;
+            spi_tr.length = SPI_SIZE_BUF * 8;
+        }
+        mtype = buf_recv[0] & ~EOS_APP_MTYPE_FLAG_MASK;
+        mtype_flags = buf_recv[0] & EOS_APP_MTYPE_FLAG_MASK;
+        len  = (uint16_t)buf_recv[1] << 8;
+        len |= (uint16_t)buf_recv[2] & 0xFF;
+        buffer = buf_recv + 3;
+
+        if (mtype == 0x00) continue;
+
+        if ((mtype <= EOS_APP_MAX_MTYPE) && (len <= EOS_APP_MTU)) {
+            app_handler[mtype - 1](mtype, buffer, len);
+        } else {
+            bad_handler(mtype, buffer, len);
+        }
+    }
+    vTaskDelete(NULL);
+}
+
+void eos_app_init(void) {
+    int i;
+
+    // Configuration for the handshake lines
+    gpio_config_t io_conf;
+
+    io_conf.intr_type = GPIO_INTR_DISABLE;
+    io_conf.mode = GPIO_MODE_OUTPUT;
+    io_conf.pull_up_en = 0;
+    io_conf.pull_down_en = 0;
+    io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_CTS);
+    gpio_config(&io_conf);
+    gpio_set_level(SPI_GPIO_CTS, 0);
+
+    io_conf.intr_type = GPIO_INTR_DISABLE;
+    io_conf.mode = GPIO_MODE_OUTPUT;
+    io_conf.pull_up_en = 0;
+    io_conf.pull_down_en = 0;
+    io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_RTS);
+    gpio_config(&io_conf);
+    gpio_set_level(SPI_GPIO_RTS, 0);
+
+    eos_msgq_init(&app_send_q, app_sndq_array, EOS_APP_SIZE_SNDQ);
+    eos_bufq_init(&app_buf_q, app_bufq_array, EOS_APP_SIZE_BUFQ);
+    for (i=0; i<EOS_APP_SIZE_BUFQ; i++) {
+        eos_bufq_push(&app_buf_q, malloc(EOS_APP_SIZE_BUF));
+    }
+
+    for (i=0; i<EOS_APP_MAX_MTYPE; i++) {
+        app_handler[i] = bad_handler;
+    }
+
+    semaph = xSemaphoreCreateCounting(EOS_APP_SIZE_BUFQ, EOS_APP_SIZE_BUFQ);
+    mutex = xSemaphoreCreateBinary();
+    xSemaphoreGive(mutex);
+    xTaskCreate(&app_xchg_task, "app_xchg", EOS_TASK_SSIZE_APP_XCHG, NULL, EOS_TASK_PRIORITY_APP_XCHG, &app_xchg_task_handle);
+    ESP_LOGI(TAG, "INIT");
+}
+
+unsigned char *eos_app_alloc(void) {
+    unsigned char *ret;
+
+    xSemaphoreTake(semaph, portMAX_DELAY);
+    xSemaphoreTake(mutex, portMAX_DELAY);
+    ret = eos_bufq_pop(&app_buf_q);
+    xSemaphoreGive(mutex);
+
+    return ret;
+}
+
+void eos_app_free(unsigned char *buf) {
+    xSemaphoreTake(mutex, portMAX_DELAY);
+    eos_bufq_push(&app_buf_q, buf);
+    xSemaphoreGive(semaph);
+    xSemaphoreGive(mutex);
+}
+
+int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t len) {
+    int rv = EOS_OK;
+
+    xSemaphoreTake(mutex, portMAX_DELAY);
+    gpio_set_level(SPI_GPIO_RTS, 1);
+    rv = eos_msgq_push(&app_send_q, mtype, buffer, len);
+    xSemaphoreGive(mutex);
+
+    if (rv) eos_app_free(buffer);
+
+    return rv;
+}
+
+void eos_app_set_handler(unsigned char mtype, eos_app_fptr_t handler) {
+    if (handler == NULL) handler = bad_handler;
+    if (mtype && (mtype <= EOS_APP_MAX_MTYPE)) app_handler[mtype - 1] = handler;
+}
diff --git a/fw/esp32/components/eos/cell_modem.c b/fw/esp32/components/eos/cell_modem.c
index 58dc97c..f5ee0a9 100644
--- a/fw/esp32/components/eos/cell_modem.c
+++ b/fw/esp32/components/eos/cell_modem.c
@@ -109,7 +109,7 @@ static void uart_data_read(uint8_t mode) {
 
                 buf = eos_net_alloc();
                 buf[0] = EOS_CELL_MTYPE_DEV | EOS_CELL_MTYPE_UART_DATA;
-                _rd = eos_modem_read(buf + 1, MIN(bsize - rd, EOS_NET_SIZE_BUF - 1), 100);
+                _rd = eos_modem_read(buf + 1, MIN(bsize - rd, EOS_NET_MTU - 1), 100);
                 eos_net_send(EOS_NET_MTYPE_CELL, buf, _rd + 1);
                 rd += _rd;
             } while (rd != bsize);
diff --git a/fw/esp32/components/eos/cell_pcm.c b/fw/esp32/components/eos/cell_pcm.c
index cf3eeb7..a022aab 100644
--- a/fw/esp32/components/eos/cell_pcm.c
+++ b/fw/esp32/components/eos/cell_pcm.c
@@ -70,7 +70,7 @@ static void i2s_event_task(void *pvParameters) {
                             hold_buf = eos_net_alloc();
                             hold_buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_PCM;
                         }
-                        if (1 + hold_bytes_r + PCM_MIC_WM <= EOS_NET_SIZE_BUF) hold_bytes_r += eos_cell_pcm_read(hold_buf + 1 + hold_bytes_r, PCM_MIC_WM);
+                        if (1 + hold_bytes_r + PCM_MIC_WM <= EOS_NET_MTU) hold_bytes_r += eos_cell_pcm_read(hold_buf + 1 + hold_bytes_r, PCM_MIC_WM);
                         if (hold_cnt == 0) {
                             eos_net_send(EOS_NET_MTYPE_CELL, hold_buf, hold_bytes_r + 1);
                             hold_bytes_r = 0;
diff --git a/fw/esp32/components/eos/cell_ussd.c b/fw/esp32/components/eos/cell_ussd.c
index a4cf32b..195feaf 100644
--- a/fw/esp32/components/eos/cell_ussd.c
+++ b/fw/esp32/components/eos/cell_ussd.c
@@ -84,7 +84,7 @@ static void ussd_reply_handler(char *urc, regmatch_t m[]) {
             _buf += _len + 1;
             len += _len + 1;
         }
-        rv = eos_modem_readln(_buf, EOS_NET_SIZE_BUF - len, 1000);
+        rv = eos_modem_readln(_buf, EOS_NET_MTU - len, 1000);
         if (rv) break;
     } while (1);
 
diff --git a/fw/esp32/components/eos/include/app.h b/fw/esp32/components/eos/include/app.h
new file mode 100644
index 0000000..2033b2b
--- /dev/null
+++ b/fw/esp32/components/eos/include/app.h
@@ -0,0 +1,23 @@
+#include <stdint.h>
+
+/* common */
+#define EOS_APP_MTU                 1500
+#define EOS_APP_SIZE_BUF            EOS_APP_MTU
+
+#define EOS_APP_MTYPE_TUN           1
+#define EOS_APP_MAX_MTYPE           8
+
+#define EOS_APP_MTYPE_FLAG_MASK     0xc0
+
+/* esp32 specific */
+#define EOS_APP_SIZE_BUFQ           4
+#define EOS_APP_SIZE_SNDQ           4
+
+typedef void (*eos_app_fptr_t) (unsigned char, unsigned char *, uint16_t);
+
+void eos_app_init(void);
+
+unsigned char *eos_app_alloc(void);
+void eos_app_free(unsigned char *buf);
+int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t len);
+void eos_app_set_handler(unsigned char mtype, eos_app_fptr_t handler);
diff --git a/fw/esp32/components/eos/include/eos.h b/fw/esp32/components/eos/include/eos.h
index 7240c83..6f420ea 100644
--- a/fw/esp32/components/eos/include/eos.h
+++ b/fw/esp32/components/eos/include/eos.h
@@ -7,19 +7,21 @@
 #define EOS_ERR_EMPTY               -11
 #define EOS_ERR_NOTFOUND            -12
 
+#define EOS_TASK_PRIORITY_NET_XCHG  1
+#define EOS_TASK_PRIORITY_APP_XCHG  1
+#define EOS_TASK_PRIORITY_UDP_RCVR  1
 #define EOS_TASK_PRIORITY_UART      1
 #define EOS_TASK_PRIORITY_MODEM     1
 #define EOS_TASK_PRIORITY_I2S       1
-#define EOS_TASK_PRIORITY_NET_XCHG  1
-#define EOS_TASK_PRIORITY_UDP_RCVR  1
-#define EOS_TASK_PRIORITY_PWR       1
 #define EOS_TASK_PRIORITY_CELL      1
+#define EOS_TASK_PRIORITY_PWR       1
 
+#define EOS_TASK_SSIZE_NET_XCHG     8192
+#define EOS_TASK_SSIZE_APP_XCHG     8192
+#define EOS_TASK_SSIZE_UDP_RCVR     4096
 #define EOS_TASK_SSIZE_UART         4096
 #define EOS_TASK_SSIZE_MODEM        4096
 #define EOS_TASK_SSIZE_I2S          4096
-#define EOS_TASK_SSIZE_NET_XCHG     8192
-#define EOS_TASK_SSIZE_UDP_RCVR     4096
-#define EOS_TASK_SSIZE_PWR          4096
 #define EOS_TASK_SSIZE_CELL         4096
+#define EOS_TASK_SSIZE_PWR          4096
 
diff --git a/fw/esp32/components/eos/include/net.h b/fw/esp32/components/eos/include/net.h
index f6b3700..cf0cb6b 100644
--- a/fw/esp32/components/eos/include/net.h
+++ b/fw/esp32/components/eos/include/net.h
@@ -1,7 +1,8 @@
 #include <stdint.h>
 
 /* common */
-#define EOS_NET_SIZE_BUF            1500
+#define EOS_NET_MTU                 1500
+#define EOS_NET_SIZE_BUF            EOS_NET_MTU
 
 #define EOS_NET_MTYPE_SOCK          1
 #define EOS_NET_MTYPE_POWER         4
diff --git a/fw/esp32/components/eos/include/tun.h b/fw/esp32/components/eos/include/tun.h
new file mode 100644
index 0000000..3acb2a6
--- /dev/null
+++ b/fw/esp32/components/eos/include/tun.h
@@ -0,0 +1 @@
+void eos_tun_init(void);
\ No newline at end of file
diff --git a/fw/esp32/components/eos/net.c b/fw/esp32/components/eos/net.c
index e48d714..0491b41 100644
--- a/fw/esp32/components/eos/net.c
+++ b/fw/esp32/components/eos/net.c
@@ -25,7 +25,8 @@
 #define SPI_GPIO_SCLK       18
 #define SPI_GPIO_CS         5
 
-#define SPI_SIZE_BUF        (EOS_NET_SIZE_BUF + 8)
+#define SPI_SIZE_BUF        (EOS_NET_SIZE_BUF + 4)
+#define SPI_SIZE_HDR        3
 
 static volatile char net_sleep = 0;
 
@@ -40,7 +41,7 @@ static SemaphoreHandle_t semaph;
 static TaskHandle_t net_xchg_task_handle;
 static const char *TAG = "EOS NET";
 
-static eos_net_fptr_t mtype_handler[EOS_NET_MAX_MTYPE];
+static eos_net_fptr_t net_handler[EOS_NET_MAX_MTYPE];
 
 static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) {
     ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len);
@@ -67,17 +68,18 @@ static void net_xchg_task(void *pvParameters) {
     unsigned char *buf_send = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA);
     unsigned char *buf_recv = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA);
     esp_err_t ret;
-    spi_slave_transaction_t spi_tr;
+
+    static spi_slave_transaction_t spi_tr;
 
     //Configuration for the SPI bus
-    spi_bus_config_t spi_bus_cfg = {
+    static spi_bus_config_t spi_bus_cfg = {
         .mosi_io_num = SPI_GPIO_MOSI,
         .miso_io_num = SPI_GPIO_MISO,
         .sclk_io_num = SPI_GPIO_SCLK
     };
 
     //Configuration for the SPI slave interface
-    spi_slave_interface_config_t spi_slave_cfg = {
+    static spi_slave_interface_config_t spi_slave_cfg = {
         .mode = 0,
         .spics_io_num = SPI_GPIO_CS,
         .queue_size = 2,
@@ -87,13 +89,13 @@ static void net_xchg_task(void *pvParameters) {
     };
 
     //Initialize SPI slave interface
-    ret = spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1);
+    ret = spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 2);
     assert(ret == ESP_OK);
 
     memset(&spi_tr, 0, sizeof(spi_tr));
-    spi_tr.length = SPI_SIZE_BUF * 8;
     spi_tr.tx_buffer = buf_send;
     spi_tr.rx_buffer = buf_recv;
+    spi_tr.length = SPI_SIZE_BUF * 8;
 
     if (eos_power_wakeup_cause()) {
         wake = 1;
@@ -111,7 +113,7 @@ static void net_xchg_task(void *pvParameters) {
                 buf_send[1] = len >> 8;
                 buf_send[2] = len & 0xFF;
                 if (buffer) {
-                    memcpy(buf_send + 3, buffer, len);
+                    memcpy(buf_send + SPI_SIZE_HDR, buffer, len);
                     eos_bufq_push(&net_buf_q, buffer);
                     xSemaphoreGive(semaph);
                 }
@@ -148,7 +150,10 @@ static void net_xchg_task(void *pvParameters) {
             eos_power_net_ready();
             wake = 0;
         }
+
+        if ((spi_tr.trans_len / 8) < SPI_SIZE_HDR) continue;
         if (buf_recv[0] == 0x00) continue;
+
         if (buf_recv[0] == 0xFF) {  // Sleep req
             if (buf_send[0] == 0) {
                 int abort = 0;
@@ -175,13 +180,14 @@ static void net_xchg_task(void *pvParameters) {
             }
             continue;
         }
+
         mtype = buf_recv[0] & ~EOS_NET_MTYPE_FLAG_MASK;
         mtype_flags = buf_recv[0] & EOS_NET_MTYPE_FLAG_MASK;
         len   = (uint16_t)buf_recv[1] << 8;
         len  |= (uint16_t)buf_recv[2] & 0xFF;
-        buffer = buf_recv + 3;
-        if ((mtype <= EOS_NET_MAX_MTYPE) && (len <= EOS_NET_SIZE_BUF)) {
-            mtype_handler[mtype-1](mtype, buffer, len);
+        buffer = buf_recv + SPI_SIZE_HDR;
+        if ((mtype <= EOS_NET_MAX_MTYPE) && (len <= EOS_NET_MTU)) {
+            net_handler[mtype - 1](mtype, buffer, len);
         } else {
             bad_handler(mtype, buffer, len);
         }
@@ -225,7 +231,7 @@ void eos_net_init(void) {
     }
 
     for (i=0; i<EOS_NET_MAX_MTYPE; i++) {
-        mtype_handler[i] = bad_handler;
+        net_handler[i] = bad_handler;
     }
 
     semaph = xSemaphoreCreateCounting(EOS_NET_SIZE_BUFQ, EOS_NET_SIZE_BUFQ);
@@ -271,7 +277,8 @@ int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len) {
 }
 
 void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler) {
-    mtype_handler[mtype-1] = handler;
+    if (handler == NULL) handler = bad_handler;
+    if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler;
 }
 
 void eos_net_sleep_done(uint8_t mode) {
diff --git a/fw/esp32/components/eos/power.c b/fw/esp32/components/eos/power.c
index 83304c2..0cbb4e0 100644
--- a/fw/esp32/components/eos/power.c
+++ b/fw/esp32/components/eos/power.c
@@ -293,7 +293,6 @@ uint8_t eos_power_wakeup_cause(void) {
             return EOS_PWR_WAKE_UART;
 
         default:
-        case ESP_SLEEP_WAKEUP_UNDEFINED:
             return EOS_PWR_WAKE_RST;
     }
 }
diff --git a/fw/esp32/components/eos/sock.c b/fw/esp32/components/eos/sock.c
index 54b09b0..355d7c7 100644
--- a/fw/esp32/components/eos/sock.c
+++ b/fw/esp32/components/eos/sock.c
@@ -84,7 +84,7 @@ static void udp_rcvr_task(void *pvParameters) {
         ssize_t rv;
 
         buf = eos_net_alloc();
-        rv = t_recvfrom(sock, buf+EOS_SOCK_SIZE_UDP_HDR, EOS_NET_SIZE_BUF-EOS_SOCK_SIZE_UDP_HDR, &addr);
+        rv = t_recvfrom(sock, buf + EOS_SOCK_SIZE_UDP_HDR, EOS_NET_MTU - EOS_SOCK_SIZE_UDP_HDR, &addr);
         if (rv < 0) {
             sock = 0;
             eos_net_free(buf);
@@ -95,7 +95,7 @@ static void udp_rcvr_task(void *pvParameters) {
         buf[1] = esock;
         memcpy(buf+2, addr.host, sizeof(addr.host));
         memcpy(buf+2+sizeof(addr.host), &addr.port, sizeof(addr.port));
-        eos_net_send(EOS_NET_MTYPE_SOCK, buf, rv+EOS_SOCK_SIZE_UDP_HDR);
+        eos_net_send(EOS_NET_MTYPE_SOCK, buf, rv + EOS_SOCK_SIZE_UDP_HDR);
     } while(sock);
     xSemaphoreTake(mutex, portMAX_DELAY);
     _socks[esock-1] = 0;
@@ -114,10 +114,10 @@ static void sock_handler(unsigned char type, unsigned char *buffer, uint16_t siz
     switch(buffer[0]) {
         case EOS_SOCK_MTYPE_PKT:
             if (size < EOS_SOCK_SIZE_UDP_HDR) return;
-            sock = _socks[buffer[1]-1];
-            memcpy(addr.host, buffer+2, sizeof(addr.host));
-            memcpy(&addr.port, buffer+2+sizeof(addr.host), sizeof(addr.port));
-            t_sendto(sock, buffer+EOS_SOCK_SIZE_UDP_HDR, size-EOS_SOCK_SIZE_UDP_HDR, &addr);
+            sock = _socks[buffer[1] - 1];
+            memcpy(addr.host, buffer + 2, sizeof(addr.host));
+            memcpy(&addr.port, buffer + 2 + sizeof(addr.host), sizeof(addr.port));
+            t_sendto(sock, buffer + EOS_SOCK_SIZE_UDP_HDR, size - EOS_SOCK_SIZE_UDP_HDR, &addr);
             break;
 
         case EOS_SOCK_MTYPE_OPEN_DGRAM:
@@ -133,7 +133,6 @@ static void sock_handler(unsigned char type, unsigned char *buffer, uint16_t siz
                 }
                 xSemaphoreGive(mutex);
             }
-            // xTaskCreatePinnedToCore(&sock_receiver, "sock_receiver", EOS_TASK_SSIZE_UDP_RCVR, (void *)esock, EOS_TASK_PRIORITY_UDP_RCVR, NULL, 1);
             xTaskCreate(&udp_rcvr_task, "udp_rcvr", EOS_TASK_SSIZE_UDP_RCVR, (void *)esock, EOS_TASK_PRIORITY_UDP_RCVR, NULL);
             rbuf = eos_net_alloc();
             rbuf[0] = EOS_SOCK_MTYPE_OPEN_DGRAM;
diff --git a/fw/esp32/components/eos/tun.c b/fw/esp32/components/eos/tun.c
new file mode 100644
index 0000000..a7181ee
--- /dev/null
+++ b/fw/esp32/components/eos/tun.c
@@ -0,0 +1,65 @@
+#include <string.h>
+#include <stdio.h>
+
+#include <lwip/pbuf.h>
+#include <lwip/netif.h>
+#include <lwip/tcpip.h>
+#include <lwip/etharp.h>
+
+#include "app.h"
+#include "tun.h"
+
+static ip4_addr_t ipaddr, netmask, gw;
+static struct netif netif_tun;
+
+static err_t ESP_IRAM_ATTR tun_output(struct netif *netif, struct pbuf *p, const struct ip4_addr *ipaddr) {
+    unsigned char *buf;
+    struct pbuf *q;
+
+    for (q = p; q != NULL; q = q->next) {
+        if (q->len > EOS_APP_MTU) continue;
+
+        buf = eos_app_alloc();
+        memcpy(buf, q->payload, q->len);
+        eos_app_send(EOS_APP_MTYPE_TUN, buf, q->len);
+    }
+
+    return ERR_OK;
+}
+
+static void ESP_IRAM_ATTR tun_input(unsigned char mtype, unsigned char *buffer, uint16_t len) {
+    struct netif *netif = &netif_tun;
+    struct pbuf *p;
+    int rv;
+
+    if (!netif_is_up(netif)) return;
+
+    p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
+    if (p == NULL) return;
+    memcpy(p->payload, buffer, len);
+    rv = netif->input(p, netif);
+    if (rv != ERR_OK) {
+        pbuf_free(p);
+    }
+}
+
+static err_t tun_init(struct netif *netif) {
+    netif->name[0] = 't';
+    netif->name[1] = 'n';
+    netif->hostname = NULL;
+    netif->output = tun_output;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP;
+    netif->mtu = 1500;
+
+    return ERR_OK;
+}
+
+void eos_tun_init(void) {
+    IP4_ADDR(&gw, 0,0,0,0);
+    IP4_ADDR(&ipaddr, 192,168,10,2);
+    IP4_ADDR(&netmask, 255,255,255,0);
+
+    netif_add(&netif_tun, &ipaddr, &netmask, &gw, NULL, tun_init, tcpip_input);
+    netif_set_up(&netif_tun);
+    eos_app_set_handler(EOS_APP_MTYPE_TUN, tun_input);
+}
\ No newline at end of file
diff --git a/fw/esp32/components/eos/wifi.c b/fw/esp32/components/eos/wifi.c
index 05c91c1..d47ae3a 100755
--- a/fw/esp32/components/eos/wifi.c
+++ b/fw/esp32/components/eos/wifi.c
@@ -75,7 +75,7 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e
                 for (i=0; i<scan_n; i++) {
                     len = strnlen((char *)scan_r[i].ssid, 33);
                     if (len > 32) continue;
-                    if (p - rbuf + len + 1 > EOS_NET_SIZE_BUF) break;
+                    if (p - rbuf + len + 1 > EOS_NET_MTU) break;
                     strcpy((char *)p, (char *)scan_r[i].ssid);
                     p += len + 1;
                 }
diff --git a/fw/esp32/main/app_main.c b/fw/esp32/main/app_main.c
index 145739c..1ae7f7c 100644
--- a/fw/esp32/main/app_main.c
+++ b/fw/esp32/main/app_main.c
@@ -12,6 +12,8 @@
 #include "_net.h"
 #include "wifi.h"
 #include "sock.h"
+#include "app.h"
+#include "tun.h"
 #include "power.h"
 
 #define ESP_INTR_FLAG_DEFAULT   0
@@ -36,7 +38,9 @@ void app_main() {
     eos_wifi_init();
     eos_sock_init();
 
+#ifdef EOS_WITH_APP
+    eos_app_init();
+    eos_tun_init();
+#endif
     eos_power_init();
 }
-
-
-- 
cgit v1.2.3