mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-25 16:27:29 +02:00
Compare commits
3 Commits
mosq-v2.0.
...
eppp-v1.0.
Author | SHA1 | Date | |
---|---|---|---|
a8631eecf5 | |||
3e28a7264c | |||
4ee9360f53 |
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(eppp): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py eppp_link
|
||||
tag_format: eppp-v$version
|
||||
version: 0.3.1
|
||||
version: 1.0.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [1.0.0](https://github.com/espressif/esp-protocols/commits/eppp-v1.0.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for custom channels ([4ee9360f](https://github.com/espressif/esp-protocols/commit/4ee9360f))
|
||||
|
||||
## [0.3.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.3.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
@ -93,4 +93,21 @@ menu "eppp_link"
|
||||
default "06:00:00:00:00:02"
|
||||
depends on EPPP_LINK_DEVICE_ETH
|
||||
|
||||
config EPPP_LINK_CHANNELS_SUPPORT
|
||||
bool "Enable channel support (multiple logical channels)"
|
||||
default n
|
||||
depends on !EPPP_LINK_DEVICE_ETH
|
||||
help
|
||||
Enable support for multiple logical channels in the EPPP link layer.
|
||||
When enabled, you can configure the number of channels used for communication.
|
||||
|
||||
config EPPP_LINK_NR_OF_CHANNELS
|
||||
int "Number of logical channels"
|
||||
depends on EPPP_LINK_CHANNELS_SUPPORT && !EPPP_LINK_DEVICE_ETH
|
||||
range 1 8
|
||||
default 2
|
||||
help
|
||||
Set the number of logical channels for EPPP link communication.
|
||||
Each channel can be used for independent data streams.
|
||||
|
||||
endmenu
|
||||
|
@ -1,7 +1,7 @@
|
||||
# ESP PPP Link component (eppp_link)
|
||||
|
||||
The component provides a general purpose connectivity engine between two microcontrollers, one acting as PPP server, the other one as PPP client.
|
||||
This component could be used for extending network using physical serial connection. Applications could vary from providing PRC engine for multiprocessor solutions to serial connection to POSIX machine. This uses a standard PPP protocol (if enabled) to negotiate IP addresses and networking, so standard PPP toolset could be used, e.g. a `pppd` service on linux. Typical application is a WiFi connectivity provider for chips that do not have WiFi.
|
||||
This component could be used for extending network using physical serial connection. Applications could vary from providing RPC engine for multiprocessor solutions to serial connection to POSIX machine. This uses a standard PPP protocol (if enabled) to negotiate IP addresses and networking, so standard PPP toolset could be used, e.g. a `pppd` service on linux. Typical application is a WiFi connectivity provider for chips that do not have WiFi.
|
||||
Uses simplified TUN network interface by default to enable faster data transfer on non-UART transports.
|
||||
|
||||
## Typical application
|
||||
@ -21,6 +21,27 @@ brings in the WiFi connectivity from the communication coprocessor.
|
||||
+----------------+ +----------------+
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Network Interface Modes
|
||||
|
||||
Standard PPP Mode (where PPP protocols is preferred) or simple tunnel using TUN Mode.
|
||||
|
||||
### Transport layer
|
||||
|
||||
UART, SPI, SDIO, Ethernet
|
||||
|
||||
### Support for logical channels
|
||||
|
||||
Allows channeling custom data (e.g. 802.11 frames)
|
||||
|
||||
## (Other) usecases
|
||||
|
||||
Besides the communication coprocessor example mentioned above, this component could be used to:
|
||||
* Bring Wi-Fi connectivity to a computer using ESP32 chip.
|
||||
* Connect your microcontroller to the internet via a pppd server (running on a raspberry)
|
||||
* Bridging two networks with two microcontrollers
|
||||
|
||||
## Configuration
|
||||
|
||||
### Choose the transport layer
|
||||
@ -39,6 +60,14 @@ Use `idf.py menuconfig` to select the transport layer:
|
||||
|
||||
Use PPP netif for UART; Keep the default (TUN) for others
|
||||
|
||||
### Channel support (multiple logical channels)
|
||||
|
||||
* `CONFIG_EPPP_LINK_CHANNELS_SUPPORT` -- Enable support for multiple logical channels (default: disabled)
|
||||
* `CONFIG_EPPP_LINK_NR_OF_CHANNELS` -- Number of logical channels (default: 2, range: 1-8, only visible if channel support is enabled)
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## API
|
||||
|
||||
@ -57,6 +86,9 @@ Use PPP netif for UART; Keep the default (TUN) for others
|
||||
* `eppp_netif_start()` -- Starts the network, could be called after startup or whenever a connection is lost
|
||||
* `eppp_netif_stop()` -- Stops the network
|
||||
* `eppp_perform()` -- Perform one iteration of the PPP task (need to be called regularly in task-less configuration)
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
* `eppp_add_channels()` -- Register channel transmit/receive callbacks (only available if channel support is enabled)
|
||||
#endif
|
||||
|
||||
## Throughput
|
||||
|
||||
|
370
components/eppp_link/detailed_description.md
Normal file
370
components/eppp_link/detailed_description.md
Normal file
@ -0,0 +1,370 @@
|
||||
# ESP PPP Link Component (eppp_link) - Detailed Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The ESP PPP Link component provides a versatile communication bridge between two ESP32 microcontrollers, enabling network connectivity over various physical transport layers. One device acts as a server (typically providing connectivity), while the other acts as a client (consuming connectivity).
|
||||
|
||||
## Network Interface Modes
|
||||
|
||||
### PPP Mode vs TUN Mode
|
||||
|
||||
The component supports two distinct network interface modes:
|
||||
|
||||
#### PPP Mode (`CONFIG_EPPP_LINK_USES_PPP=y`)
|
||||
- **Standard PPP Protocol**: Uses the Point-to-Point Protocol (RFC 1661) with full LCP negotiation
|
||||
- **Compatibility**: Compatible with standard PPP implementations like Linux `pppd`
|
||||
- **Features**:
|
||||
- Automatic IP address negotiation
|
||||
- Link Control Protocol (LCP) for connection establishment
|
||||
- Authentication support (if configured)
|
||||
- Standard PPP framing with escape sequences
|
||||
- **Use Case**: When interfacing with standard PPP-capable systems or when full PPP compatibility is required
|
||||
- **Transport Limitation**: Primarily designed for UART transport due to PPP's serial nature
|
||||
|
||||
#### TUN Mode (`CONFIG_EPPP_LINK_USES_PPP=n`, default)
|
||||
- **Simplified Packet Interface**: Uses a custom packet-based protocol without PPP negotiation
|
||||
- **Performance**: Faster data transfer due to reduced protocol overhead
|
||||
- **Features**:
|
||||
- Direct IP packet transmission
|
||||
- Custom framing for packet boundaries
|
||||
- No negotiation overhead
|
||||
- Static IP address configuration
|
||||
- **Use Case**: Default mode for ESP-to-ESP communication, optimal for non-UART transports
|
||||
- **Transport Support**: Works efficiently with all transport types (UART, SPI, SDIO, Ethernet)
|
||||
|
||||
**Mode Selection**: Configure via `idf.py menuconfig` → `Component config` → `eppp_link` → `Use PPP network interface`
|
||||
|
||||
## Transport Layer Options
|
||||
|
||||
### UART Transport
|
||||
- **Configuration**: `CONFIG_EPPP_LINK_DEVICE_UART=y`
|
||||
- **Features**:
|
||||
- Simple serial communication
|
||||
- Configurable baud rate (up to 3Mbps tested)
|
||||
- Hardware flow control support
|
||||
- Custom framing for packet boundaries in TUN mode
|
||||
- **Performance**: ~2 Mbps (TCP/UDP) @ 3 Mbaud
|
||||
- **Use Case**: Basic connectivity, long-distance communication, debugging
|
||||
- **Pins**: TX, RX configurable
|
||||
|
||||
```c
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = 25;
|
||||
config.uart.rx_io = 26;
|
||||
config.uart.baud = 921600;
|
||||
```
|
||||
|
||||
### SPI Transport
|
||||
- **Configuration**: `CONFIG_EPPP_LINK_DEVICE_SPI=y`
|
||||
- **Features**:
|
||||
- Master/slave configuration
|
||||
- GPIO interrupt signaling for flow control
|
||||
- Configurable clock frequency
|
||||
- Full-duplex communication
|
||||
- Packet queue for transmission
|
||||
- **Performance**: ~5 Mbps (TCP), ~8 Mbps (UDP) @ 16MHz
|
||||
- **Use Case**: High-speed local communication, PCB-level connections
|
||||
- **Pins**: MOSI, MISO, SCLK, CS, interrupt GPIO
|
||||
|
||||
```c
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
config.spi.is_master = true;
|
||||
config.spi.freq = 16000000;
|
||||
config.spi.mosi = 11;
|
||||
config.spi.miso = 13;
|
||||
config.spi.sclk = 12;
|
||||
config.spi.cs = 10;
|
||||
config.spi.intr = 2;
|
||||
```
|
||||
|
||||
### SDIO Transport
|
||||
- **Configuration**: `CONFIG_EPPP_LINK_DEVICE_SDIO=y`
|
||||
- **Features**:
|
||||
- Host/slave configuration
|
||||
- High-speed data transfer
|
||||
- 1-bit or 4-bit bus width
|
||||
- Hardware flow control
|
||||
- **Performance**: ~9 Mbps (TCP), ~11 Mbps (UDP)
|
||||
- **Use Case**: Highest throughput applications, module-to-module communication
|
||||
- **Pins**: CLK, CMD, D0-D3 (configurable width)
|
||||
|
||||
```c
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.transport = EPPP_TRANSPORT_SDIO;
|
||||
config.sdio.is_host = true;
|
||||
config.sdio.width = 4;
|
||||
config.sdio.clk = 18;
|
||||
config.sdio.cmd = 19;
|
||||
config.sdio.d0 = 14;
|
||||
// ... additional data pins
|
||||
```
|
||||
|
||||
### Ethernet Transport
|
||||
- **Configuration**: `CONFIG_EPPP_LINK_DEVICE_ETH=y`
|
||||
- **Features**:
|
||||
- Direct MAC-to-MAC communication
|
||||
- Can work with or without PHY chips
|
||||
- Standard Ethernet framing
|
||||
- Automatic task management (no `eppp_perform()` needed)
|
||||
- **Performance**: ~5 Mbps (TCP), ~8 Mbps (UDP) with internal EMAC
|
||||
- **Use Case**: Board-to-board communication, integration with existing Ethernet infrastructure
|
||||
- **Pins**: MDC, MDIO, plus PHY-specific pins
|
||||
|
||||
```c
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.transport = EPPP_TRANSPORT_ETHERNET;
|
||||
config.ethernet.mdc_io = 23;
|
||||
config.ethernet.mdio_io = 18;
|
||||
config.ethernet.phy_addr = 1;
|
||||
config.ethernet.rst_io = 5;
|
||||
```
|
||||
|
||||
## Channel Support (Multiple Logical Channels)
|
||||
|
||||
### Overview
|
||||
Channel support allows multiplexing multiple independent data streams over a single transport connection. This enables applications to separate different types of data (e.g., network traffic, control commands, sensor data) into distinct logical channels.
|
||||
|
||||
### Configuration
|
||||
- **Enable**: `CONFIG_EPPP_LINK_CHANNELS_SUPPORT=y`
|
||||
- **Count**: `CONFIG_EPPP_LINK_NR_OF_CHANNELS` (1-8 channels, default 2)
|
||||
- **Limitation**: Not available for Ethernet transport
|
||||
|
||||
### Channel Usage
|
||||
```c
|
||||
// Channel callback function type
|
||||
typedef esp_err_t (*eppp_channel_fn_t)(esp_netif_t *netif, int nr, void *buffer, size_t len);
|
||||
|
||||
// Register channel callbacks
|
||||
esp_err_t eppp_add_channels(esp_netif_t *netif,
|
||||
eppp_channel_fn_t *tx, // Transmit function pointer (output)
|
||||
const eppp_channel_fn_t rx, // Receive callback (input)
|
||||
void* context); // User context
|
||||
|
||||
// Get user context
|
||||
void* eppp_get_context(esp_netif_t *netif);
|
||||
```
|
||||
|
||||
### Channel Example
|
||||
```c
|
||||
// Channel 0: Default network traffic (handled automatically)
|
||||
// Channel 1: Control/chat messages
|
||||
// Channel 2: WiFi data forwarding
|
||||
|
||||
static esp_err_t channel_receive(esp_netif_t *netif, int channel, void *buffer, size_t len)
|
||||
{
|
||||
switch(channel) {
|
||||
case 1: // Control channel
|
||||
process_control_message(buffer, len);
|
||||
break;
|
||||
case 2: // WiFi channel
|
||||
forward_to_wifi(buffer, len);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown channel %d", channel);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Register channels
|
||||
eppp_channel_fn_t tx_func;
|
||||
eppp_add_channels(netif, &tx_func, channel_receive, user_context);
|
||||
|
||||
// Transmit on specific channel
|
||||
tx_func(netif, 1, "Hello", 5); // Send to channel 1
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Simple API (Recommended for most use cases)
|
||||
|
||||
#### Client Side
|
||||
```c
|
||||
esp_netif_t *eppp_connect(eppp_config_t *config);
|
||||
```
|
||||
- **Purpose**: Simplified client connection
|
||||
- **Behavior**: Blocks until connection is established
|
||||
- **Returns**: Configured network interface or NULL on failure
|
||||
- **Use Case**: Simple applications that don't need fine-grained control
|
||||
|
||||
#### Server Side
|
||||
```c
|
||||
esp_netif_t *eppp_listen(eppp_config_t *config);
|
||||
```
|
||||
- **Purpose**: Simplified server listening
|
||||
- **Behavior**: Blocks until client connects
|
||||
- **Returns**: Configured network interface or NULL on failure
|
||||
- **Use Case**: Simple applications that don't need fine-grained control
|
||||
|
||||
#### Connection Management
|
||||
```c
|
||||
void eppp_close(esp_netif_t *netif);
|
||||
```
|
||||
- **Purpose**: Close connection and cleanup resources
|
||||
- **Behavior**: Stops tasks, closes transport, destroys network interface
|
||||
|
||||
### Advanced API (Manual Control)
|
||||
|
||||
#### Initialization
|
||||
```c
|
||||
esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config);
|
||||
```
|
||||
- **Purpose**: Initialize endpoint without starting communication
|
||||
- **Parameters**:
|
||||
- `role`: `EPPP_SERVER` or `EPPP_CLIENT`
|
||||
- `config`: Transport and network configuration
|
||||
- **Returns**: Network interface handle
|
||||
- **Use Case**: Applications needing manual control over connection lifecycle
|
||||
|
||||
#### Connection Control
|
||||
```c
|
||||
esp_err_t eppp_netif_start(esp_netif_t *netif);
|
||||
esp_err_t eppp_netif_stop(esp_netif_t *netif, int stop_timeout_ms);
|
||||
```
|
||||
- **Purpose**: Manual network interface start/stop
|
||||
- **Use Case**: Dynamic connection management, error recovery
|
||||
|
||||
#### Task Management
|
||||
```c
|
||||
esp_err_t eppp_perform(esp_netif_t *netif);
|
||||
```
|
||||
- **Purpose**: Single iteration of communication task
|
||||
- **Returns**:
|
||||
- `ESP_OK`: Continue operation
|
||||
- `ESP_FAIL`: Operation failed but should continue
|
||||
- `ESP_ERR_TIMEOUT`: Stop operation requested
|
||||
- **Use Case**: Task-less operation, integration with custom task schedulers
|
||||
- **Note**: Not needed for Ethernet transport (has its own task)
|
||||
|
||||
#### Resource Management
|
||||
```c
|
||||
void eppp_deinit(esp_netif_t *netif);
|
||||
```
|
||||
- **Purpose**: Clean up resources without stopping tasks
|
||||
- **Use Case**: Manual resource management
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Basic Client-Server Setup
|
||||
|
||||
**Client (Host) Configuration:**
|
||||
```c
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = 25;
|
||||
config.uart.rx_io = 26;
|
||||
config.uart.baud = 921600;
|
||||
|
||||
esp_netif_t *netif = eppp_connect(&config);
|
||||
if (netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to connect");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Connected successfully");
|
||||
// Use network interface for communication
|
||||
}
|
||||
```
|
||||
|
||||
**Server (Slave) Configuration:**
|
||||
```c
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Initialize WiFi or other network interface
|
||||
init_wifi();
|
||||
|
||||
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = 26; // Crossed with client
|
||||
config.uart.rx_io = 25; // Crossed with client
|
||||
config.uart.baud = 921600;
|
||||
|
||||
esp_netif_t *netif = eppp_listen(&config);
|
||||
if (netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to setup server");
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable NAT to share WiFi connection
|
||||
ESP_ERROR_CHECK(esp_netif_napt_enable(netif));
|
||||
ESP_LOGI(TAG, "Server ready");
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced Manual Control
|
||||
```c
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.task.run_task = false; // Disable automatic task
|
||||
|
||||
esp_netif_t *netif = eppp_init(EPPP_CLIENT, &config);
|
||||
if (netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to initialize");
|
||||
return;
|
||||
}
|
||||
|
||||
// Start network interface
|
||||
ESP_ERROR_CHECK(eppp_netif_start(netif));
|
||||
|
||||
// Custom task loop
|
||||
while (true) {
|
||||
esp_err_t ret = eppp_perform(netif);
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
ESP_LOGI(TAG, "Operation stopped");
|
||||
break;
|
||||
} else if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Operation failed: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
// Add custom processing here
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
|
||||
eppp_deinit(netif);
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Channel Configuration
|
||||
```c
|
||||
typedef struct {
|
||||
eppp_channel_fn_t tx_func;
|
||||
esp_netif_t *netif;
|
||||
} channel_context_t;
|
||||
|
||||
static esp_err_t channel_rx(esp_netif_t *netif, int channel, void *buffer, size_t len)
|
||||
{
|
||||
ESP_LOGI(TAG, "Channel %d received %d bytes", channel, len);
|
||||
// Process channel data based on channel number
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void setup_channels(void)
|
||||
{
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
esp_netif_t *netif = eppp_connect(&config);
|
||||
|
||||
channel_context_t *ctx = calloc(1, sizeof(channel_context_t));
|
||||
ctx->netif = netif;
|
||||
|
||||
// Register channel callbacks
|
||||
ESP_ERROR_CHECK(eppp_add_channels(netif, &ctx->tx_func, channel_rx, ctx));
|
||||
|
||||
// Send data on channel 1
|
||||
const char *msg = "Hello on channel 1";
|
||||
ctx->tx_func(netif, 1, (void*)msg, strlen(msg));
|
||||
}
|
||||
```
|
@ -367,3 +367,24 @@ void eppp_close(esp_netif_t *netif)
|
||||
eppp_deinit(netif);
|
||||
remove_handlers();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
esp_err_t eppp_add_channels(esp_netif_t *netif, eppp_channel_fn_t *tx, const eppp_channel_fn_t rx, void* context)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(netif != NULL && tx != NULL && rx != NULL, ESP_ERR_INVALID_ARG, TAG, "Invalid arguments");
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
ESP_RETURN_ON_FALSE(h != NULL && h->channel_tx != NULL, ESP_ERR_INVALID_STATE, TAG, "Transport not initialized");
|
||||
*tx = h->channel_tx;
|
||||
h->channel_rx = rx;
|
||||
h->context = context;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void* eppp_get_context(esp_netif_t *netif)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(netif != NULL, NULL, TAG, "Invalid netif");
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
ESP_RETURN_ON_FALSE(h != NULL, NULL, TAG, "EPPP Not initialized");
|
||||
return h->context;
|
||||
}
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "eppp_link.h"
|
||||
#include "eppp_transport.h"
|
||||
#include "eppp_transport_sdio.h"
|
||||
#include "eppp_sdio.h"
|
||||
|
||||
#define TAG "eppp_sdio"
|
||||
|
||||
@ -67,6 +68,9 @@ eppp_transport_handle_t eppp_sdio_init(struct eppp_config_sdio_s *config)
|
||||
ESP_RETURN_ON_FALSE(config, NULL, TAG, "Config cannot be null");
|
||||
struct eppp_sdio *h = calloc(1, sizeof(struct eppp_sdio));
|
||||
ESP_RETURN_ON_FALSE(h, NULL, TAG, "Failed to allocate eppp_handle");
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
h->parent.channel_tx = eppp_sdio_transmit_channel;
|
||||
#endif
|
||||
h->parent.base.post_attach = post_attach;
|
||||
h->is_host = config->is_host;
|
||||
esp_err_t (*init_fn)(struct eppp_config_sdio_s * eppp_config) = h->is_host ? eppp_sdio_host_init : eppp_sdio_slave_init;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -8,8 +8,10 @@
|
||||
#define MAX_SDIO_PAYLOAD 1500
|
||||
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
|
||||
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
|
||||
#define SDIO_PACKET_SIZE SDIO_ALIGN(MAX_SDIO_PAYLOAD + 4)
|
||||
#define PPP_SOF 0x7E
|
||||
|
||||
|
||||
// Interrupts and registers
|
||||
#define SLAVE_INTR 0
|
||||
#define SLAVE_REG_REQ 0
|
||||
@ -17,3 +19,11 @@
|
||||
// Requests from host to slave
|
||||
#define REQ_RESET 1
|
||||
#define REQ_INIT 2
|
||||
|
||||
struct header {
|
||||
uint8_t magic;
|
||||
uint8_t channel;
|
||||
uint16_t size;
|
||||
} __attribute__((packed));
|
||||
|
||||
esp_err_t eppp_sdio_transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,6 +15,7 @@
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "esp_check.h"
|
||||
#include "eppp_link.h"
|
||||
#include "eppp_transport.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
|
||||
|
||||
@ -28,22 +29,23 @@ static SemaphoreHandle_t s_essl_mutex = NULL;
|
||||
static essl_handle_t s_essl = NULL;
|
||||
static sdmmc_card_t *s_card = NULL;
|
||||
|
||||
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
|
||||
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
|
||||
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PACKET_SIZE];
|
||||
static DMA_ATTR uint8_t rcv_buffer[SDIO_PACKET_SIZE];
|
||||
|
||||
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
|
||||
static esp_err_t eppp_sdio_host_tx_generic(int channel, void *buffer, size_t len)
|
||||
{
|
||||
if (s_essl == NULL || s_essl_mutex == NULL) {
|
||||
// silently skip the Tx if the SDIO not fully initialized
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
memcpy(send_buffer, buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len);
|
||||
if (send_len > len) {
|
||||
// pad with SOF's
|
||||
memset(&send_buffer[len], PPP_SOF, send_len - len);
|
||||
}
|
||||
|
||||
struct header *head = (void *)send_buffer;
|
||||
head->magic = PPP_SOF;
|
||||
head->channel = channel;
|
||||
head->size = len;
|
||||
memcpy(send_buffer + sizeof(struct header), buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len + sizeof(struct header));
|
||||
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
|
||||
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
|
||||
if (ret != ESP_OK) {
|
||||
@ -56,6 +58,19 @@ esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
return eppp_sdio_host_tx_generic(0, buffer, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
esp_err_t eppp_sdio_transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len)
|
||||
{
|
||||
return eppp_sdio_host_tx_generic(channel, buffer, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static esp_err_t request_slave_reset(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
@ -145,15 +160,37 @@ esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
|
||||
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
|
||||
esp_err_t ret;
|
||||
do {
|
||||
size_t size_read = SDIO_PAYLOAD;
|
||||
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
|
||||
size_t size_read = SDIO_PACKET_SIZE;
|
||||
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PACKET_SIZE, &size_read, PACKET_TIMEOUT_MS);
|
||||
if (ret == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "interrupt but no data can be read");
|
||||
break;
|
||||
} else if (ret == ESP_OK) {
|
||||
ESP_LOGD(TAG, "receive data, size: %d", size_read);
|
||||
struct header *head = (void *)rcv_buffer;
|
||||
if (head->magic != PPP_SOF) {
|
||||
ESP_LOGE(TAG, "invalid magic %x", head->magic);
|
||||
break;
|
||||
}
|
||||
if (head->channel > NR_OF_CHANNELS) {
|
||||
ESP_LOGE(TAG, "invalid channel %x", head->channel);
|
||||
break;
|
||||
}
|
||||
if (head->size > SDIO_PAYLOAD || head->size > size_read) {
|
||||
ESP_LOGE(TAG, "invalid size %x", head->size);
|
||||
break;
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
|
||||
if (head->channel == 0) {
|
||||
esp_netif_receive(netif, rcv_buffer + sizeof(struct header), head->size, NULL);
|
||||
} else {
|
||||
#if defined(CONFIG_EPPP_LINK_CHANNELS_SUPPORT)
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->channel_rx) {
|
||||
h->channel_rx(netif, head->channel, rcv_buffer + sizeof(struct header), head->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "rx packet error: %08X", ret);
|
||||
|
@ -10,9 +10,9 @@
|
||||
#include "esp_netif.h"
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "eppp_link.h"
|
||||
#include "eppp_transport.h"
|
||||
#include "eppp_sdio.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAVE
|
||||
#define BUFFER_NUM 4
|
||||
#define BUFFER_SIZE SDIO_PAYLOAD
|
||||
@ -21,19 +21,18 @@ static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
|
||||
static DMA_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
|
||||
static int s_slave_request = 0;
|
||||
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
static esp_err_t eppp_sdio_host_tx_generic(int channel, void *buffer, size_t len)
|
||||
{
|
||||
if (s_slave_request != REQ_INIT) {
|
||||
// silently skip the Tx if the SDIO not fully initialized
|
||||
return ESP_OK;
|
||||
}
|
||||
memcpy(sdio_slave_tx_buffer, buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len);
|
||||
if (send_len > len) {
|
||||
// pad with SOF's if the size is not 4 bytes aligned
|
||||
memset(&sdio_slave_tx_buffer[len], PPP_SOF, send_len - len);
|
||||
}
|
||||
|
||||
struct header *head = (void *)sdio_slave_tx_buffer;
|
||||
head->magic = PPP_SOF;
|
||||
head->channel = channel;
|
||||
head->size = len;
|
||||
memcpy(sdio_slave_tx_buffer + sizeof(struct header), buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len + sizeof(struct header));
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
|
||||
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
|
||||
if (ret != ESP_OK) {
|
||||
@ -44,6 +43,18 @@ esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
return eppp_sdio_host_tx_generic(0, buffer, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
esp_err_t eppp_sdio_transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len)
|
||||
{
|
||||
return eppp_sdio_host_tx_generic(channel, buffer, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t slave_reset(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
@ -82,7 +93,29 @@ esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||
again:
|
||||
ptr = sdio_slave_recv_get_buf(handle, &length);
|
||||
esp_netif_receive(netif, ptr, length, NULL);
|
||||
struct header *head = (void *)ptr;
|
||||
if (head->magic != PPP_SOF) {
|
||||
ESP_LOGE(TAG, "invalid magic %x", head->magic);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (head->channel > NR_OF_CHANNELS) {
|
||||
ESP_LOGE(TAG, "invalid channel %x", head->channel);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (head->size > SDIO_PAYLOAD || head->size > length) {
|
||||
ESP_LOGE(TAG, "invalid size %x", head->size);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (head->channel == 0) {
|
||||
esp_netif_receive(netif, ptr + sizeof(struct header), head->size, NULL);
|
||||
} else {
|
||||
#if defined(CONFIG_EPPP_LINK_CHANNELS_SUPPORT)
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->channel_rx) {
|
||||
h->channel_rx(netif, head->channel, ptr + sizeof(struct header), head->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to recycle packet buffer");
|
||||
return ESP_FAIL;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_check.h"
|
||||
@ -24,7 +25,8 @@
|
||||
|
||||
#define MAX_PAYLOAD 1500
|
||||
#define MIN_TRIGGER_US 20
|
||||
#define SPI_HEADER_MAGIC 0x1234
|
||||
#define PPP_SOF 0x7E
|
||||
#define SPI_HEADER_MAGIC PPP_SOF
|
||||
#define SPI_ALIGN(size) (((size) + 3U) & ~(3U))
|
||||
#define TRANSFER_SIZE SPI_ALIGN((MAX_PAYLOAD + 6))
|
||||
#define NEXT_TRANSACTION_SIZE(a,b) (((a)>(b))?(a):(b)) /* next transaction: whichever is bigger */
|
||||
@ -32,10 +34,12 @@
|
||||
struct packet {
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
int channel;
|
||||
};
|
||||
|
||||
struct header {
|
||||
uint16_t magic;
|
||||
uint8_t magic;
|
||||
uint8_t channel;
|
||||
uint16_t size;
|
||||
uint16_t next_size;
|
||||
uint16_t check;
|
||||
@ -65,12 +69,10 @@ struct eppp_spi {
|
||||
esp_timer_handle_t timer;
|
||||
};
|
||||
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
static esp_err_t transmit_generic(struct eppp_spi *handle, int channel, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *common = h;
|
||||
struct eppp_spi *handle = __containerof(common, struct eppp_spi, parent);;
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
struct packet buf = { };
|
||||
|
||||
struct packet buf = { .channel = channel };
|
||||
uint8_t *current_buffer = buffer;
|
||||
size_t remaining = len;
|
||||
do { // TODO(IDF-9194): Refactor this loop to allocate only once and perform
|
||||
@ -100,14 +102,25 @@ static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
}
|
||||
gpio_set_level(handle->gpio_intr, 0);
|
||||
}
|
||||
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_WARN);
|
||||
uart_write_bytes(handle->uart_port, buffer, len);
|
||||
#endif // DEVICE UART or SPI
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *handle = h;
|
||||
struct eppp_spi *spi_handle = __containerof(handle, struct eppp_spi, parent);;
|
||||
return transmit_generic(spi_handle, 0, buffer, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
static esp_err_t transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *handle = esp_netif_get_io_driver(netif);
|
||||
struct eppp_spi *spi_handle = __containerof(handle, struct eppp_spi, parent);;
|
||||
return transmit_generic(spi_handle, channel, buffer, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void IRAM_ATTR timer_callback(void *arg)
|
||||
{
|
||||
struct eppp_spi *h = arg;
|
||||
@ -339,6 +352,7 @@ esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
if (h->outbound.len <= h->transaction_size && allow_test_tx == false) {
|
||||
// sending outbound
|
||||
head->size = h->outbound.len;
|
||||
head->channel = h->outbound.channel;
|
||||
if (h->outbound.len > 0) {
|
||||
memcpy(out_buf + sizeof(struct header), h->outbound.data, h->outbound.len);
|
||||
free(h->outbound.data);
|
||||
@ -355,6 +369,7 @@ esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
} else {
|
||||
// outbound is bigger, need to transmit in another transaction (keep this empty)
|
||||
head->size = 0;
|
||||
head->channel = 0;
|
||||
}
|
||||
next_tx_size = head->next_size = h->outbound.len;
|
||||
head->magic = SPI_HEADER_MAGIC;
|
||||
@ -367,17 +382,25 @@ esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
}
|
||||
head = (void *)in_buf;
|
||||
uint16_t check = esp_rom_crc16_le(0, in_buf, sizeof(struct header) - sizeof(uint16_t));
|
||||
if (check != head->check || head->magic != SPI_HEADER_MAGIC) {
|
||||
if (check != head->check || head->magic != SPI_HEADER_MAGIC || head->channel > NR_OF_CHANNELS) {
|
||||
h->transaction_size = 0; // need to start with HEADER only transaction
|
||||
if (allow_test_tx) {
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Wrong checksum or magic");
|
||||
ESP_LOGE(TAG, "Wrong checksum, magic, or channel: %x %x %x", check, head->magic, head->channel);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (head->size > 0) {
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, in_buf + sizeof(struct header), head->size, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(netif, in_buf + sizeof(struct header), head->size, NULL);
|
||||
if (head->channel == 0) {
|
||||
esp_netif_receive(netif, in_buf + sizeof(struct header), head->size, NULL);
|
||||
} else {
|
||||
#if defined(CONFIG_EPPP_LINK_CHANNELS_SUPPORT)
|
||||
if (h->parent.channel_rx) {
|
||||
h->parent.channel_rx(netif, head->channel, in_buf + sizeof(struct header), head->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
h->transaction_size = NEXT_TRANSACTION_SIZE(next_tx_size, head->next_size);
|
||||
return ESP_OK;
|
||||
@ -415,6 +438,9 @@ eppp_transport_handle_t eppp_spi_init(struct eppp_config_spi_s *config)
|
||||
ESP_RETURN_ON_FALSE(config, NULL, TAG, "Config cannot be null");
|
||||
struct eppp_spi *h = calloc(1, sizeof(struct eppp_spi));
|
||||
ESP_RETURN_ON_FALSE(h, NULL, TAG, "Failed to allocate eppp_handle");
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
h->parent.channel_tx = transmit_channel;
|
||||
#endif
|
||||
h->is_master = config->is_master;
|
||||
h->parent.base.post_attach = post_attach;
|
||||
h->out_queue = xQueueCreate(CONFIG_EPPP_LINK_PACKET_QUEUE_SIZE, sizeof(struct packet));
|
||||
|
@ -5,6 +5,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "esp_netif_types.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
#define NR_OF_CHANNELS CONFIG_EPPP_LINK_NR_OF_CHANNELS
|
||||
#else
|
||||
#define NR_OF_CHANNELS 1
|
||||
#endif
|
||||
|
||||
struct eppp_handle {
|
||||
esp_netif_driver_base_t base;
|
||||
@ -12,6 +19,11 @@ struct eppp_handle {
|
||||
bool stop;
|
||||
bool exited;
|
||||
bool netif_stop;
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
eppp_channel_fn_t channel_tx;
|
||||
eppp_channel_fn_t channel_rx;
|
||||
void* context;
|
||||
#endif
|
||||
};
|
||||
|
||||
esp_err_t eppp_check_connection(esp_netif_t *netif);
|
||||
|
@ -31,19 +31,19 @@ struct eppp_uart {
|
||||
|
||||
struct header {
|
||||
uint8_t magic;
|
||||
uint8_t channel;
|
||||
uint8_t check;
|
||||
uint16_t size;
|
||||
} __attribute__((packed));
|
||||
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
static esp_err_t transmit_generic(struct eppp_uart *handle, int channel, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *common = h;
|
||||
struct eppp_uart *handle = __containerof(common, struct eppp_uart, parent);
|
||||
#ifndef CONFIG_EPPP_LINK_USES_PPP
|
||||
static uint8_t out_buf[MAX_PACKET_SIZE] = {};
|
||||
struct header *head = (void *)out_buf;
|
||||
head->magic = HEADER_MAGIC;
|
||||
head->check = 0;
|
||||
head->channel = channel;
|
||||
head->size = len;
|
||||
head->check = (0xFF & len) ^ (len >> 8);
|
||||
memcpy(out_buf + sizeof(struct header), buffer, len);
|
||||
@ -56,6 +56,22 @@ static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *handle = h;
|
||||
struct eppp_uart *uart_handle = __containerof(handle, struct eppp_uart, parent);
|
||||
return transmit_generic(uart_handle, 0, buffer, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
static esp_err_t transmit_channel(esp_netif_t *netif, int channel, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *handle = esp_netif_get_io_driver(netif);
|
||||
struct eppp_uart *uart_handle = __containerof(handle, struct eppp_uart, parent);
|
||||
return transmit_generic(uart_handle, channel, buffer, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t init_uart(struct eppp_uart *h, struct eppp_config_uart_s *config)
|
||||
{
|
||||
h->uart_port = config->port;
|
||||
@ -122,6 +138,7 @@ static void process_packet(esp_netif_t *netif, uart_port_t uart_port, size_t ava
|
||||
|
||||
// Check if we have the complete packet
|
||||
uint16_t payload_size = head->size;
|
||||
int channel = head->channel;
|
||||
size_t total_packet_size = sizeof(struct header) + payload_size;
|
||||
|
||||
if (payload_size > MAX_PAYLOAD) {
|
||||
@ -136,7 +153,15 @@ static void process_packet(esp_netif_t *netif, uart_port_t uart_port, size_t ava
|
||||
}
|
||||
|
||||
// Got a complete packet, pass it to network
|
||||
esp_netif_receive(netif, in_buf + buf_start + sizeof(struct header), payload_size, NULL);
|
||||
if (channel == 0) {
|
||||
esp_netif_receive(netif, in_buf + buf_start + sizeof(struct header), payload_size, NULL);
|
||||
} else {
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
if (h->parent.channel_rx) {
|
||||
h->parent.channel_rx(netif, channel, in_buf + buf_start + sizeof(struct header), payload_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Advance start pointer past this packet
|
||||
buf_start += total_packet_size;
|
||||
@ -237,6 +262,9 @@ eppp_transport_handle_t eppp_uart_init(struct eppp_config_uart_s *config)
|
||||
ESP_RETURN_ON_FALSE(config, NULL, TAG, "Config cannot be null");
|
||||
struct eppp_uart *h = calloc(1, sizeof(struct eppp_uart));
|
||||
ESP_RETURN_ON_FALSE(h, NULL, TAG, "Failed to allocate eppp_handle");
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
h->parent.channel_tx = transmit_channel;
|
||||
#endif
|
||||
h->parent.base.post_attach = post_attach;
|
||||
ESP_GOTO_ON_ERROR(init_uart(h, config), err, TAG, "Failed to init UART");
|
||||
return &h->parent;
|
||||
|
@ -1,2 +1,6 @@
|
||||
if(CONFIG_EXAMPLE_WIFI_OVER_EPPP_CHANNEL)
|
||||
set(wifi_over_channels channel_wifi_station.c)
|
||||
endif()
|
||||
idf_component_register(SRCS app_main.c register_iperf.c
|
||||
INCLUDE_DIRS ".")
|
||||
${wifi_over_channels}
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -106,4 +106,14 @@ menu "Example Configuration"
|
||||
help
|
||||
Baudrate used by the PPP over UART
|
||||
|
||||
config EXAMPLE_WIFI_OVER_EPPP_CHANNEL
|
||||
bool "Use WiFi over EPPP channel"
|
||||
default n
|
||||
depends on EPPP_LINK_CHANNELS_SUPPORT && ESP_WIFI_REMOTE_ENABLED
|
||||
help
|
||||
Enable this option to use WiFi over EPPP channel.
|
||||
If this option is enabled, the example will only start the Wi-Fi driver,
|
||||
but the Wi-Fi netif will reside on client's end and will channel
|
||||
the Rx and Tx data via EPPP channels.
|
||||
|
||||
endmenu
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "esp_netif.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "console_ping.h"
|
||||
|
||||
@ -88,6 +89,7 @@ static void mqtt_app_start(void)
|
||||
}
|
||||
#endif // MQTT
|
||||
|
||||
void station_over_eppp_channel(void *arg);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
@ -156,6 +158,9 @@ void app_main(void)
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_start());
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_WIFI_OVER_EPPP_CHANNEL
|
||||
station_over_eppp_channel(eppp_netif);
|
||||
#endif
|
||||
#if CONFIG_EXAMPLE_MQTT
|
||||
mqtt_app_start();
|
||||
#endif
|
||||
|
185
components/eppp_link/examples/host/main/channel_wifi_station.c
Normal file
185
components/eppp_link/examples/host/main/channel_wifi_station.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_wifi_remote.h"
|
||||
|
||||
#define CHAT_CHANNEL 1
|
||||
#define WIFI_CHANNEL 2
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN,
|
||||
HELLO,
|
||||
START,
|
||||
ERROR,
|
||||
} state_t;
|
||||
|
||||
typedef struct context {
|
||||
eppp_channel_fn_t transmit;
|
||||
EventGroupHandle_t flags;
|
||||
state_t state;
|
||||
esp_netif_t *eppp;
|
||||
} context_t;
|
||||
|
||||
#define HELLO_BIT BIT0
|
||||
#define START_BIT BIT1
|
||||
#define CONNECT_BIT BIT2
|
||||
#define SERVER_UP_BIT BIT3
|
||||
|
||||
#define ALL_BITS (HELLO_BIT | START_BIT | CONNECT_BIT | SERVER_UP_BIT)
|
||||
|
||||
static uint8_t s_wifi_mac_addr[6] = { 0 };
|
||||
static const char *TAG = "eppp_host_example_with_channels";
|
||||
|
||||
esp_netif_t* esp_wifi_remote_create_default_sta(void);
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "IP event_handler: event_base=%s event_id=%d", event_base, event_id);
|
||||
if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||
ESP_LOGI(TAG, "Got IP:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_remote_get_mac(wifi_interface_t ifx, uint8_t mac[6])
|
||||
{
|
||||
if (ifx != WIFI_IF_STA) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
||||
}
|
||||
for (int i = 0; i < sizeof(s_wifi_mac_addr); i++) {
|
||||
if (s_wifi_mac_addr[i] == 0) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
memcpy(mac, s_wifi_mac_addr, sizeof(s_wifi_mac_addr));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t eppp_receive(esp_netif_t *netif, int nr, void *buffer, size_t len)
|
||||
{
|
||||
context_t *ctx = eppp_get_context(netif);
|
||||
if (nr == CHAT_CHANNEL) {
|
||||
ESP_LOGI(TAG, "Received channel=%d len=%d %.*s", nr, (int)len, (int)len, (char *)buffer);
|
||||
const char hello[] = "Hello client";
|
||||
const char mac[] = "MAC: ";
|
||||
const char connected[] = "Connected";
|
||||
const char server_up[] = "Server up";
|
||||
size_t mac_len = 5 /* MAC: */ + 6 * 2 /* 6 bytes per char */ + 5 /* : */ + 1 /* \0 */;
|
||||
if (len == sizeof(server_up) && memcmp(buffer, server_up, len) == 0) {
|
||||
if (ctx->state == UNKNOWN) {
|
||||
ESP_LOGI(TAG, "Server is up");
|
||||
ctx->state = HELLO;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Received server up in unexpected state %d", ctx->state);
|
||||
ctx->state = ERROR;
|
||||
}
|
||||
xEventGroupSetBits(ctx->flags, SERVER_UP_BIT);
|
||||
} else if (len == sizeof(hello) && memcmp(buffer, hello, len) == 0) {
|
||||
if (ctx->state == HELLO) {
|
||||
xEventGroupSetBits(ctx->flags, HELLO_BIT);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Received hello in unexpected state %d", ctx->state);
|
||||
ctx->state = ERROR;
|
||||
}
|
||||
} else if (len == mac_len && memcmp(buffer, mac, 5) == 0) {
|
||||
if (ctx->state == HELLO) {
|
||||
uint8_t mac_addr[6];
|
||||
sscanf((char *)buffer + 5, "%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8 ":%2" PRIx8,
|
||||
&mac_addr[0], &mac_addr[1], &mac_addr[2], &mac_addr[3], &mac_addr[4], &mac_addr[5]);
|
||||
ESP_LOGI(TAG, "Parsed MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
memcpy(s_wifi_mac_addr, mac_addr, sizeof(s_wifi_mac_addr));
|
||||
xEventGroupSetBits(ctx->flags, START_BIT);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Received MAC in unexpected state %d", ctx->state);
|
||||
ctx->state = ERROR;
|
||||
}
|
||||
} else if (len == sizeof(connected) && memcmp(buffer, connected, len) == 0) {
|
||||
if (ctx->state == START) {
|
||||
xEventGroupSetBits(ctx->flags, CONNECT_BIT);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Received connected in unexpected state %d", ctx->state);
|
||||
ctx->state = ERROR;
|
||||
}
|
||||
}
|
||||
} else if (nr == WIFI_CHANNEL) {
|
||||
ESP_LOGD(TAG, "Received WIFI channel=%d len=%d", nr, (int)len);
|
||||
ESP_LOG_BUFFER_HEXDUMP("wifi-receive", buffer, len, ESP_LOG_VERBOSE);
|
||||
return esp_wifi_remote_channel_rx(ctx->eppp, buffer, NULL, len);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Incorrect channel number %d", nr);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t wifi_transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
esp_netif_t *eppp = (esp_netif_t *)h;
|
||||
context_t *ctx = eppp_get_context(eppp);
|
||||
ESP_LOG_BUFFER_HEXDUMP("wifi-transmit", buffer, len, ESP_LOG_VERBOSE);
|
||||
return ctx->transmit(eppp, WIFI_CHANNEL, buffer, len);
|
||||
}
|
||||
|
||||
void esp_netif_destroy_wifi_remote(void *esp_netif);
|
||||
|
||||
void station_over_eppp_channel(void *arg)
|
||||
{
|
||||
__attribute__((unused)) esp_err_t ret;
|
||||
esp_netif_t *wifi = NULL;
|
||||
context_t ctx = {
|
||||
.transmit = NULL,
|
||||
.flags = NULL,
|
||||
.state = UNKNOWN,
|
||||
.eppp = (esp_netif_t *)arg
|
||||
};
|
||||
ESP_GOTO_ON_FALSE(ctx.eppp != NULL, ESP_FAIL, err, TAG, "Incorrect EPPP netif");
|
||||
ESP_GOTO_ON_FALSE(ctx.flags = xEventGroupCreate(), ESP_FAIL, err, TAG, "Failed to create event group");
|
||||
ESP_GOTO_ON_ERROR(eppp_add_channels(ctx.eppp, &ctx.transmit, eppp_receive, &ctx), err, TAG, "Failed to add channels");
|
||||
ESP_GOTO_ON_FALSE(ctx.transmit, ESP_FAIL, err, TAG, "Channel tx function is not set");
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_remote_channel_set(WIFI_IF_STA, ctx.eppp, wifi_transmit), err, TAG, "Failed to set wifi channel tx function");
|
||||
esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, &ctx);
|
||||
|
||||
while (1) {
|
||||
EventBits_t bits = xEventGroupWaitBits(ctx.flags, ALL_BITS, pdTRUE, pdFALSE, pdMS_TO_TICKS(1000));
|
||||
if (bits & HELLO_BIT) {
|
||||
ESP_LOGI(TAG, "Hello done");
|
||||
if (wifi == NULL) {
|
||||
wifi = esp_wifi_remote_create_default_sta();
|
||||
}
|
||||
const char command[] = "Get MAC";
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)command, sizeof(command));
|
||||
} else if (bits & START_BIT) {
|
||||
ctx.state = START;
|
||||
ESP_LOGI(TAG, "Starting WIFI");
|
||||
esp_event_post(WIFI_REMOTE_EVENT, WIFI_EVENT_STA_START, NULL, 0, 0);
|
||||
} else if (bits & CONNECT_BIT) {
|
||||
ESP_LOGI(TAG, "WIFI connected");
|
||||
esp_event_post(WIFI_REMOTE_EVENT, WIFI_EVENT_STA_CONNECTED, NULL, 0, 0);
|
||||
} else if ((bits & SERVER_UP_BIT) == SERVER_UP_BIT || ctx.state != START) {
|
||||
if (ctx.state == ERROR) {
|
||||
esp_netif_destroy_wifi_remote(wifi);
|
||||
wifi = NULL;
|
||||
ESP_LOGI(TAG, "WiFi netif has been destroyed");
|
||||
}
|
||||
const char hello[] = "Hello server";
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)hello, sizeof(hello));
|
||||
ctx.state = HELLO;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
vTaskDelete(NULL);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
dependencies:
|
||||
espressif/iperf-cmd: "^0.1.1"
|
||||
espressif/iperf-cmd: ^0.1.1
|
||||
espressif/eppp_link:
|
||||
version: "*"
|
||||
override_path: "../../.."
|
||||
version: '*'
|
||||
override_path: ../../..
|
||||
console_cmd_ping:
|
||||
version: "*"
|
||||
version: '*'
|
||||
|
@ -1,2 +1,6 @@
|
||||
idf_component_register(SRCS "eppp_slave.c"
|
||||
INCLUDE_DIRS ".")
|
||||
if(CONFIG_EXAMPLE_WIFI_OVER_EPPP_CHANNEL)
|
||||
set(wifi_over_channels channel_wifi_station.c)
|
||||
endif()
|
||||
idf_component_register(SRCS eppp_slave.c
|
||||
${wifi_over_channels}
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -98,4 +98,14 @@ menu "Example Configuration"
|
||||
help
|
||||
Baudrate used by the PPP over UART
|
||||
|
||||
config EXAMPLE_WIFI_OVER_EPPP_CHANNEL
|
||||
bool "Use WiFi over EPPP channel"
|
||||
default n
|
||||
depends on EPPP_LINK_CHANNELS_SUPPORT
|
||||
help
|
||||
Enable this option to use WiFi over EPPP channel.
|
||||
If this option is enabled, the example will only start the Wi-Fi driver,
|
||||
but the Wi-Fi netif will reside on client's end and will channel
|
||||
the Rx and Tx data via EPPP channels.
|
||||
|
||||
endmenu
|
||||
|
169
components/eppp_link/examples/slave/main/channel_wifi_station.c
Normal file
169
components/eppp_link/examples/slave/main/channel_wifi_station.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_private/wifi.h"
|
||||
|
||||
#define CHAT_CHANNEL 1
|
||||
#define WIFI_CHANNEL 2
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN,
|
||||
HELLO,
|
||||
START,
|
||||
ERROR,
|
||||
} state_t;
|
||||
|
||||
typedef struct context {
|
||||
eppp_channel_fn_t transmit;
|
||||
EventGroupHandle_t flags;
|
||||
state_t state;
|
||||
esp_netif_t *eppp;
|
||||
} context_t;
|
||||
|
||||
#define HELLO_BIT BIT0
|
||||
#define START_BIT BIT1
|
||||
#define CONNECT_BIT BIT2
|
||||
#define DISCONNECT_BIT BIT3
|
||||
|
||||
#define ALL_BITS (HELLO_BIT | START_BIT | CONNECT_BIT | DISCONNECT_BIT)
|
||||
|
||||
static const char *TAG = "eppp_host_example_with_channels";
|
||||
static context_t *s_eppp_channel_ctx = NULL;
|
||||
|
||||
static esp_err_t eppp_receive(esp_netif_t *netif, int nr, void *buffer, size_t len)
|
||||
{
|
||||
context_t *ctx = eppp_get_context(netif);
|
||||
if (nr == CHAT_CHANNEL) {
|
||||
ESP_LOGI(TAG, "Received channel=%d len=%d %.*s", nr, (int)len, (int)len, (char *)buffer);
|
||||
const char hello[] = "Hello server";
|
||||
const char mac[] = "Get MAC";
|
||||
if (len == sizeof(hello) && memcmp(buffer, hello, len) == 0) {
|
||||
if (ctx->state == HELLO) {
|
||||
xEventGroupSetBits(ctx->flags, HELLO_BIT);
|
||||
} else {
|
||||
ctx->state = ERROR;
|
||||
}
|
||||
} else if (len == sizeof(mac) && memcmp(buffer, mac, 5) == 0) {
|
||||
if (ctx->state == HELLO) {
|
||||
xEventGroupSetBits(ctx->flags, START_BIT);
|
||||
} else {
|
||||
ctx->state = ERROR;
|
||||
}
|
||||
}
|
||||
} else if (nr == WIFI_CHANNEL) {
|
||||
ESP_LOGD(TAG, "Received WIFI channel=%d len=%d", nr, (int)len);
|
||||
ESP_LOG_BUFFER_HEXDUMP("wifi-receive", buffer, len, ESP_LOG_VERBOSE);
|
||||
return esp_wifi_internal_tx(WIFI_IF_STA, buffer, len);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Incorrect channel number %d", nr);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t wifi_receive(void *buffer, uint16_t len, void *eb)
|
||||
{
|
||||
s_eppp_channel_ctx->transmit(s_eppp_channel_ctx->eppp, WIFI_CHANNEL, buffer, len);
|
||||
esp_wifi_internal_free_rx_buffer(eb);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
context_t *ctx = arg;
|
||||
ESP_LOGI(TAG, "event_handler: event_base=%s event_id=%d", event_base, event_id);
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
ESP_LOGI(TAG, "WIFI start event");
|
||||
esp_wifi_connect();
|
||||
xEventGroupSetBits(ctx->flags, CONNECT_BIT);
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
ESP_LOGI(TAG, "connect to the AP fail");
|
||||
xEventGroupSetBits(ctx->flags, DISCONNECT_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void init_wifi_driver(context_t *ctx)
|
||||
{
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
|
||||
event_handler, ctx));
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = CONFIG_ESP_WIFI_SSID,
|
||||
.password = CONFIG_ESP_WIFI_PASSWORD,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
}
|
||||
|
||||
void station_over_eppp_channel(void *arg)
|
||||
{
|
||||
__attribute__((unused)) esp_err_t ret;
|
||||
context_t ctx = {
|
||||
.transmit = NULL,
|
||||
.flags = NULL,
|
||||
.state = UNKNOWN,
|
||||
.eppp = (esp_netif_t *)arg
|
||||
};
|
||||
ESP_GOTO_ON_FALSE(ctx.flags = xEventGroupCreate(), ESP_FAIL, err, TAG, "Failed to create event group");
|
||||
ESP_GOTO_ON_ERROR(eppp_add_channels(ctx.eppp, &ctx.transmit, eppp_receive, &ctx), err, TAG, "Failed to add channels");
|
||||
ESP_GOTO_ON_FALSE(ctx.transmit, ESP_FAIL, err, TAG, "Channel tx function is not set");
|
||||
init_wifi_driver(&ctx);
|
||||
|
||||
while (1) {
|
||||
EventBits_t bits = xEventGroupWaitBits(ctx.flags, ALL_BITS, pdTRUE, pdFALSE, pdMS_TO_TICKS(1000));
|
||||
if (bits & HELLO_BIT) {
|
||||
ESP_LOGI(TAG, "Hello from client received");
|
||||
const char hello[] = "Hello client";
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)hello, sizeof(hello));
|
||||
} else if (bits & START_BIT) {
|
||||
ctx.state = START;
|
||||
ESP_LOGI(TAG, "Starting WIFI");
|
||||
uint8_t mac[6];
|
||||
if (esp_wifi_get_mac(WIFI_IF_STA, mac) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_wifi_get_mac failed");
|
||||
ctx.state = ERROR;
|
||||
continue;
|
||||
}
|
||||
char mac_data[5 /* MAC: */ + 6 * 2 /* 6 bytes per char */ + 5 /* : */ + 1 /* \0 */];
|
||||
sprintf(mac_data, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
ESP_LOGI(TAG, "Sending MAC: %.*s", (int)sizeof(mac_data), mac_data);
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)mac_data, sizeof(mac_data));
|
||||
ret = esp_wifi_start();
|
||||
ESP_LOGI(TAG, "WIFI start result: %d", ret);
|
||||
s_eppp_channel_ctx = &ctx;
|
||||
esp_wifi_internal_reg_rxcb(WIFI_IF_STA, wifi_receive);
|
||||
} else if (bits & CONNECT_BIT) {
|
||||
ESP_LOGI(TAG, "WIFI connected");
|
||||
const char connected[] = "Connected";
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)connected, sizeof(connected));
|
||||
} else if (bits & DISCONNECT_BIT) {
|
||||
const char disconnected[] = "Disconnected";
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)disconnected, sizeof(disconnected));
|
||||
} else if (ctx.state != START) {
|
||||
ctx.state = HELLO;
|
||||
const char up[] = "Server up";
|
||||
esp_wifi_disconnect();
|
||||
esp_wifi_stop();
|
||||
ctx.transmit(ctx.eppp, CHAT_CHANNEL, (void*)up, sizeof(up));
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
vTaskDelete(NULL);
|
||||
}
|
@ -11,12 +11,14 @@
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "eppp_link.h"
|
||||
#include "inttypes.h"
|
||||
|
||||
static const char *TAG = "eppp_slave";
|
||||
|
||||
#if CONFIG_SOC_WIFI_SUPPORTED
|
||||
#if defined(CONFIG_SOC_WIFI_SUPPORTED) && !defined(CONFIG_EXAMPLE_WIFI_OVER_EPPP_CHANNEL)
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected*/
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
@ -27,12 +29,13 @@ static EventGroupHandle_t s_wifi_event_group;
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "event_handler: event_base=%s event_id=%" PRIi32, event_base, event_id);
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
ESP_LOGI(TAG, "WIFI start event");
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY) {
|
||||
@ -107,12 +110,15 @@ void init_network_interface(void)
|
||||
}
|
||||
#else
|
||||
|
||||
// If the SoC does not have WiFi capabilities, we can initialize a different network interface, this function is a placeholder for that purpose.
|
||||
// This function is also a no-op if EXAMPLE_WIFI_OVER_EPPP_CHANNEL==1, since the Wi-Fi network interface will live on the other peer (on the host side).
|
||||
void init_network_interface(void)
|
||||
{
|
||||
// placeholder to initialize any other network interface if WiFi is not available
|
||||
}
|
||||
|
||||
#endif // SoC WiFi capable chip
|
||||
#endif // SoC WiFi capable chip || WiFi over EPPP channel
|
||||
|
||||
void station_over_eppp_channel(void *arg);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
@ -153,5 +159,9 @@ void app_main(void)
|
||||
ESP_LOGE(TAG, "Failed to setup connection");
|
||||
return ;
|
||||
}
|
||||
#ifdef CONFIG_EXAMPLE_WIFI_OVER_EPPP_CHANNEL
|
||||
station_over_eppp_channel(eppp_netif);
|
||||
#else
|
||||
ESP_ERROR_CHECK(esp_netif_napt_enable(eppp_netif));
|
||||
#endif // CONFIG_EXAMPLE_WIFI_OVER_EPPP_CHANNEL
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 0.3.1
|
||||
version: 1.0.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
|
||||
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
|
||||
dependencies:
|
||||
|
@ -5,6 +5,10 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EPPP_DEFAULT_SERVER_IP() ESP_IP4TOADDR(192, 168, 11, 1)
|
||||
#define EPPP_DEFAULT_CLIENT_IP() ESP_IP4TOADDR(192, 168, 11, 2)
|
||||
|
||||
@ -110,7 +114,6 @@ typedef enum eppp_transport {
|
||||
|
||||
typedef struct eppp_config_t {
|
||||
eppp_transport_t transport;
|
||||
|
||||
struct eppp_config_spi_s {
|
||||
int host;
|
||||
bool is_master;
|
||||
@ -203,3 +206,15 @@ void eppp_netif_deinit(esp_netif_t *netif);
|
||||
* - ESP_ERR_TIMEOUT indicates that the operation was requested to stop
|
||||
*/
|
||||
esp_err_t eppp_perform(esp_netif_t *netif);
|
||||
|
||||
#ifdef CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
typedef esp_err_t (*eppp_channel_fn_t)(esp_netif_t *netif, int nr, void *buffer, size_t len);
|
||||
|
||||
esp_err_t eppp_add_channels(esp_netif_t *netif, eppp_channel_fn_t *tx, const eppp_channel_fn_t rx, void* context);
|
||||
|
||||
void* eppp_get_context(esp_netif_t *netif);
|
||||
#endif // CONFIG_EPPP_LINK_CHANNELS_SUPPORT
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user