Skip to content

Commit 711541b

Browse files
committed
feat(eppp): Add support for custom channels
1 parent ea9f29a commit 711541b

21 files changed

+698
-55
lines changed

components/eppp_link/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,21 @@ menu "eppp_link"
9393
default "06:00:00:00:00:02"
9494
depends on EPPP_LINK_DEVICE_ETH
9595

96+
config EPPP_LINK_CHANNELS_SUPPORT
97+
bool "Enable channel support (multiple logical channels)"
98+
default n
99+
depends on !EPPP_LINK_DEVICE_ETH
100+
help
101+
Enable support for multiple logical channels in the EPPP link layer.
102+
When enabled, you can configure the number of channels used for communication.
103+
104+
config EPPP_LINK_NR_OF_CHANNELS
105+
int "Number of logical channels"
106+
depends on EPPP_LINK_CHANNELS_SUPPORT && !EPPP_LINK_DEVICE_ETH
107+
range 1 8
108+
default 2
109+
help
110+
Set the number of logical channels for EPPP link communication.
111+
Each channel can be used for independent data streams.
112+
96113
endmenu

components/eppp_link/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ Use `idf.py menuconfig` to select the transport layer:
3939

4040
Use PPP netif for UART; Keep the default (TUN) for others
4141

42+
### Channel support (multiple logical channels)
43+
44+
* `CONFIG_EPPP_LINK_CHANNELS_SUPPORT` -- Enable support for multiple logical channels (default: disabled)
45+
* `CONFIG_EPPP_LINK_NR_OF_CHANNELS` -- Number of logical channels (default: 2, range: 1-8, only visible if channel support is enabled)
46+
47+
When channel support is enabled, the EPPP link can multiplex multiple logical data streams over the same transport. The number of channels is configurable. Channel support is not available for Ethernet transport.
48+
49+
To use channels in your application, use the `eppp_add_channels()` API and provide your own channel transmit/receive callbacks. These APIs and related types are only available when channel support is enabled in Kconfig.
4250

4351
## API
4452

@@ -57,6 +65,9 @@ Use PPP netif for UART; Keep the default (TUN) for others
5765
* `eppp_netif_start()` -- Starts the network, could be called after startup or whenever a connection is lost
5866
* `eppp_netif_stop()` -- Stops the network
5967
* `eppp_perform()` -- Perform one iteration of the PPP task (need to be called regularly in task-less configuration)
68+
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
69+
* `eppp_add_channels()` -- Register channel transmit/receive callbacks (only available if channel support is enabled)
70+
#endif
6071

6172
## Throughput
6273

components/eppp_link/eppp_link.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,24 @@ void eppp_close(esp_netif_t *netif)
367367
eppp_deinit(netif);
368368
remove_handlers();
369369
}
370+
371+
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
372+
esp_err_t eppp_add_channels(esp_netif_t *netif, eppp_channel_fn_t *tx, const eppp_channel_fn_t rx, void* context)
373+
{
374+
ESP_RETURN_ON_FALSE(netif != NULL && tx != NULL && rx != NULL, ESP_ERR_INVALID_ARG, TAG, "Invalid arguments");
375+
struct eppp_handle *h = esp_netif_get_io_driver(netif);
376+
ESP_RETURN_ON_FALSE(h != NULL && h->channel_tx != NULL, ESP_ERR_INVALID_STATE, TAG, "Transport not initialized");
377+
*tx = h->channel_tx;
378+
h->channel_rx = rx;
379+
h->context = context;
380+
return ESP_OK;
381+
}
382+
383+
void* eppp_get_context(esp_netif_t *netif)
384+
{
385+
ESP_RETURN_ON_FALSE(netif != NULL, NULL, TAG, "Invalid netif");
386+
struct eppp_handle *h = esp_netif_get_io_driver(netif);
387+
ESP_RETURN_ON_FALSE(h != NULL, NULL, TAG, "EPPP Not initialized");
388+
return h->context;
389+
}
390+
#endif

components/eppp_link/eppp_sdio.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "eppp_link.h"
1414
#include "eppp_transport.h"
1515
#include "eppp_transport_sdio.h"
16+
#include "eppp_sdio.h"
1617

1718
#define TAG "eppp_sdio"
1819

@@ -67,6 +68,9 @@ eppp_transport_handle_t eppp_sdio_init(struct eppp_config_sdio_s *config)
6768
ESP_RETURN_ON_FALSE(config, NULL, TAG, "Config cannot be null");
6869
struct eppp_sdio *h = calloc(1, sizeof(struct eppp_sdio));
6970
ESP_RETURN_ON_FALSE(h, NULL, TAG, "Failed to allocate eppp_handle");
71+
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
72+
h->parent.channel_tx = eppp_sdio_transmit_channel;
73+
#endif
7074
h->parent.base.post_attach = post_attach;
7175
h->is_host = config->is_host;
7276
esp_err_t (*init_fn)(struct eppp_config_sdio_s * eppp_config) = h->is_host ? eppp_sdio_host_init : eppp_sdio_slave_init;

components/eppp_link/eppp_sdio.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -8,12 +8,22 @@
88
#define MAX_SDIO_PAYLOAD 1500
99
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
1010
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
11+
#define SDIO_PACKET_SIZE SDIO_ALIGN(MAX_SDIO_PAYLOAD + 4)
1112
#define PPP_SOF 0x7E
1213

14+
1315
// Interrupts and registers
1416
#define SLAVE_INTR 0
1517
#define SLAVE_REG_REQ 0
1618

1719
// Requests from host to slave
1820
#define REQ_RESET 1
1921
#define REQ_INIT 2
22+
23+
struct header {
24+
uint8_t magic;
25+
uint8_t channel;
26+
uint16_t size;
27+
} __attribute__((packed));
28+
29+
esp_err_t eppp_sdio_transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len);

components/eppp_link/eppp_sdio_host.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -15,6 +15,7 @@
1515
#include "sdmmc_cmd.h"
1616
#include "esp_check.h"
1717
#include "eppp_link.h"
18+
#include "eppp_transport.h"
1819

1920
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
2021

@@ -28,22 +29,27 @@ static SemaphoreHandle_t s_essl_mutex = NULL;
2829
static essl_handle_t s_essl = NULL;
2930
static sdmmc_card_t *s_card = NULL;
3031

31-
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
32-
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
32+
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PACKET_SIZE];
33+
static DMA_ATTR uint8_t rcv_buffer[SDIO_PACKET_SIZE];
3334

34-
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
35+
static esp_err_t eppp_sdio_host_tx_generic(int channel, void *buffer, size_t len)
3536
{
3637
if (s_essl == NULL || s_essl_mutex == NULL) {
3738
// silently skip the Tx if the SDIO not fully initialized
3839
return ESP_OK;
3940
}
4041

41-
memcpy(send_buffer, buffer, len);
42-
size_t send_len = SDIO_ALIGN(len);
43-
if (send_len > len) {
44-
// pad with SOF's
45-
memset(&send_buffer[len], PPP_SOF, send_len - len);
46-
}
42+
43+
struct header *head = (void *)send_buffer;
44+
head->magic = PPP_SOF;
45+
head->channel = channel;
46+
head->size = len;
47+
memcpy(send_buffer + sizeof(struct header), buffer, len);
48+
size_t send_len = SDIO_ALIGN(len + sizeof(struct header));
49+
// if (send_len > len) {
50+
// // pad with SOF's
51+
// memset(&send_buffer[len], PPP_SOF, send_len - len);
52+
// }
4753
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
4854
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
4955
if (ret != ESP_OK) {
@@ -56,6 +62,19 @@ esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
5662
return ret;
5763
}
5864

65+
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
66+
{
67+
return eppp_sdio_host_tx_generic(0, buffer, len);
68+
}
69+
70+
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
71+
esp_err_t eppp_sdio_transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len)
72+
{
73+
return eppp_sdio_host_tx_generic(channel, buffer, len);
74+
}
75+
#endif
76+
77+
5978
static esp_err_t request_slave_reset(void)
6079
{
6180
esp_err_t ret = ESP_OK;
@@ -145,15 +164,37 @@ esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
145164
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
146165
esp_err_t ret;
147166
do {
148-
size_t size_read = SDIO_PAYLOAD;
149-
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
167+
size_t size_read = SDIO_PACKET_SIZE;
168+
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PACKET_SIZE, &size_read, PACKET_TIMEOUT_MS);
150169
if (ret == ESP_ERR_NOT_FOUND) {
151170
ESP_LOGE(TAG, "interrupt but no data can be read");
152171
break;
153172
} else if (ret == ESP_OK) {
154173
ESP_LOGD(TAG, "receive data, size: %d", size_read);
174+
struct header *head = (void *)rcv_buffer;
175+
if (head->magic != PPP_SOF) {
176+
ESP_LOGE(TAG, "invalid magic %x", head->magic);
177+
break;
178+
}
179+
if (head->channel > NR_OF_CHANNELS) {
180+
ESP_LOGE(TAG, "invalid channel %x", head->channel);
181+
break;
182+
}
183+
if (head->size > SDIO_PAYLOAD || head->size > size_read) {
184+
ESP_LOGE(TAG, "invalid size %x", head->size);
185+
break;
186+
}
155187
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
156-
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
188+
if (head->channel == 0) {
189+
esp_netif_receive(netif, rcv_buffer + sizeof(struct header), head->size, NULL);
190+
} else {
191+
#if defined(CONFIG_EPPP_LINK_CHANNELS_SUPPORT)
192+
struct eppp_handle *h = esp_netif_get_io_driver(netif);
193+
if (h->channel_rx) {
194+
h->channel_rx(netif, head->channel, rcv_buffer + sizeof(struct header), head->size);
195+
}
196+
#endif
197+
}
157198
break;
158199
} else {
159200
ESP_LOGE(TAG, "rx packet error: %08X", ret);

components/eppp_link/eppp_sdio_slave.c

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#include "esp_netif.h"
1111
#include "driver/sdio_slave.h"
1212
#include "eppp_link.h"
13+
#include "eppp_transport.h"
1314
#include "eppp_sdio.h"
1415
#include "esp_check.h"
15-
1616
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAVE
1717
#define BUFFER_NUM 4
1818
#define BUFFER_SIZE SDIO_PAYLOAD
@@ -21,19 +21,18 @@ static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
2121
static DMA_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
2222
static int s_slave_request = 0;
2323

24-
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
24+
static esp_err_t eppp_sdio_host_tx_generic(int channel, void *buffer, size_t len)
2525
{
2626
if (s_slave_request != REQ_INIT) {
2727
// silently skip the Tx if the SDIO not fully initialized
2828
return ESP_OK;
2929
}
30-
memcpy(sdio_slave_tx_buffer, buffer, len);
31-
size_t send_len = SDIO_ALIGN(len);
32-
if (send_len > len) {
33-
// pad with SOF's if the size is not 4 bytes aligned
34-
memset(&sdio_slave_tx_buffer[len], PPP_SOF, send_len - len);
35-
}
36-
30+
struct header *head = (void *)sdio_slave_tx_buffer;
31+
head->magic = PPP_SOF;
32+
head->channel = channel;
33+
head->size = len;
34+
memcpy(sdio_slave_tx_buffer + sizeof(struct header), buffer, len);
35+
size_t send_len = SDIO_ALIGN(len + sizeof(struct header));
3736
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
3837
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
3938
if (ret != ESP_OK) {
@@ -44,6 +43,18 @@ esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
4443
return ESP_OK;
4544
}
4645

46+
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
47+
{
48+
return eppp_sdio_host_tx_generic(0, buffer, len);
49+
}
50+
51+
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
52+
esp_err_t eppp_sdio_transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len)
53+
{
54+
return eppp_sdio_host_tx_generic(channel, buffer, len);
55+
}
56+
#endif
57+
4758
static esp_err_t slave_reset(void)
4859
{
4960
esp_err_t ret = ESP_OK;
@@ -82,7 +93,29 @@ esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
8293
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
8394
again:
8495
ptr = sdio_slave_recv_get_buf(handle, &length);
85-
esp_netif_receive(netif, ptr, length, NULL);
96+
struct header *head = (void *)ptr;
97+
if (head->magic != PPP_SOF) {
98+
ESP_LOGE(TAG, "invalid magic %x", head->magic);
99+
return ESP_FAIL;
100+
}
101+
if (head->channel > NR_OF_CHANNELS) {
102+
ESP_LOGE(TAG, "invalid channel %x", head->channel);
103+
return ESP_FAIL;
104+
}
105+
if (head->size > SDIO_PAYLOAD || head->size > length) {
106+
ESP_LOGE(TAG, "invalid size %x", head->size);
107+
return ESP_FAIL;
108+
}
109+
if (head->channel == 0) {
110+
esp_netif_receive(netif, ptr + sizeof(struct header), head->size, NULL);
111+
} else {
112+
#if defined(CONFIG_EPPP_LINK_CHANNELS_SUPPORT)
113+
struct eppp_handle *h = esp_netif_get_io_driver(netif);
114+
if (h->channel_rx) {
115+
h->channel_rx(netif, head->channel, ptr + sizeof(struct header), head->size);
116+
}
117+
#endif
118+
}
86119
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
87120
ESP_LOGE(TAG, "Failed to recycle packet buffer");
88121
return ESP_FAIL;

0 commit comments

Comments
 (0)