mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-23 15:27:28 +02:00
feat(examples): Move the slip example to esp-netif folder
And update the slip_modem_get_ipv6_address() to return the address by copy instead of reference (to employ return value optimizaiton where possible)
This commit is contained in:
@ -0,0 +1,8 @@
|
||||
# SLIP Modem Component
|
||||
|
||||
idf_component_register(
|
||||
SRCS "library/slip_modem.c" "library/slip_modem_netif.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES esp_netif driver
|
||||
)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_netif.h"
|
||||
#include "driver/uart.h"
|
||||
|
||||
/** @brief Configuration of SLIP network interface
|
||||
*
|
||||
*/
|
||||
#define ESP_NETIF_INHERENT_DEFAULT_SLIP() \
|
||||
{ \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \
|
||||
.get_ip_event = 0, \
|
||||
.lost_ip_event = 0, \
|
||||
.if_key = "SLP_DEF", \
|
||||
.if_desc = "slip", \
|
||||
.route_prio = 16, \
|
||||
.bridge_info = NULL \
|
||||
};
|
||||
|
||||
extern esp_netif_netstack_config_t *netstack_default_slip;
|
||||
|
||||
typedef struct slip_modem slip_modem_t;
|
||||
|
||||
// Filter callbacks for handling application specific slip messages
|
||||
typedef bool slip_rx_filter_cb_t(slip_modem_t *slip, uint8_t *data, uint32_t len);
|
||||
|
||||
|
||||
/** @brief Configuration structure for SLIP modem interface
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uart_port_t uart_dev; /* UART device for reading and writing SLIP information, this must be initialised externally */
|
||||
|
||||
int uart_tx_pin; /* UART TX pin number */
|
||||
int uart_rx_pin; /* UART TX pin number */
|
||||
|
||||
uint32_t uart_baud; /* UART baud rate */
|
||||
|
||||
uint32_t rx_buffer_len; /* Length of buffer for RX messages */
|
||||
|
||||
slip_rx_filter_cb_t *rx_filter; /* Filter for parsing out non-SLIP messages from incoming SLIP stream */
|
||||
esp_ip6_addr_t *ipv6_addr;
|
||||
|
||||
} slip_modem_config_t;
|
||||
|
||||
|
||||
|
||||
/** @brief Create a slip modem
|
||||
*
|
||||
* @param[in] slip configured esp netif
|
||||
* @param[in] configuration for the slip modem
|
||||
*
|
||||
* @returns
|
||||
* - slip modem driver glue object
|
||||
*/
|
||||
slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config);
|
||||
|
||||
/** @brief Destroy a slip modem
|
||||
*
|
||||
* @param[in] slip modem object for destruction
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t slip_modem_destroy(slip_modem_t *slip);
|
||||
|
||||
/**
|
||||
* @brief Getter for the internally configured IPv6 address
|
||||
*
|
||||
* @param[in] slip modem object
|
||||
*
|
||||
* @returns
|
||||
* - ipv6 address returned by copy
|
||||
*/
|
||||
esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip);
|
||||
|
||||
/**
|
||||
* @brief Data path API that forward the supplied data to the attached network interface
|
||||
*
|
||||
* @param[in] slip modem object
|
||||
* @param[in] buffer pointer to the outgoing data
|
||||
* @param[in] len length of the data
|
||||
*
|
||||
*/
|
||||
void slip_modem_raw_write(slip_modem_t *slip, void *buffer, size_t len);
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "slip_modem.h"
|
||||
|
||||
#include "esp_netif.h"
|
||||
#include "slip_modem_netif.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define SLIP_RX_TASK_PRIORITY 10
|
||||
#define SLIP_RX_TASK_STACK_SIZE (4 * 1024)
|
||||
|
||||
static const char *TAG = "slip-modem";
|
||||
|
||||
|
||||
// UART container object
|
||||
typedef struct {
|
||||
// UART device number for SIO use
|
||||
uart_port_t uart_dev;
|
||||
|
||||
// UART baud rate for configuration
|
||||
uint32_t uart_baud;
|
||||
|
||||
// UART TX pin for configuration
|
||||
int uart_tx_pin;
|
||||
|
||||
// UART RX pin for configuration
|
||||
int uart_rx_pin;
|
||||
|
||||
// QueueHandle for uart driver
|
||||
QueueHandle_t uart_queue;
|
||||
|
||||
// TaskHandle for receive task
|
||||
TaskHandle_t uart_rx_task;
|
||||
} esp_slip_uart_t;
|
||||
|
||||
|
||||
// Modem object, implements glue logic for slip_driver and esp_netif
|
||||
struct slip_modem {
|
||||
// ESP base netif driver
|
||||
esp_netif_driver_base_t base;
|
||||
|
||||
// Uart for use with slip
|
||||
esp_slip_uart_t uart;
|
||||
|
||||
// Buffer for incoming messages
|
||||
uint8_t *buffer;
|
||||
uint32_t buffer_len;
|
||||
|
||||
// Filter callbacks for application-specific slip message handling
|
||||
slip_rx_filter_cb_t *rx_filter;
|
||||
|
||||
// Running flag
|
||||
bool running;
|
||||
|
||||
// esp_netif related: SLIP interface IP6 address
|
||||
esp_ip6_addr_t addr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
static void slip_modem_uart_rx_task(void *arg);
|
||||
static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args);
|
||||
|
||||
// Create a new slip modem
|
||||
slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif);
|
||||
|
||||
ESP_LOGD(TAG, "%s (netif: %p)", __func__, slip_netif);
|
||||
|
||||
slip_modem_t *slip_modem = calloc(1, sizeof(slip_modem_t));
|
||||
if (!slip_modem) {
|
||||
ESP_LOGE(TAG, "create netif glue failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Attach driver and post_attach callbacks
|
||||
slip_modem->base.post_attach = slip_modem_post_attach;
|
||||
slip_modem->base.netif = slip_netif;
|
||||
|
||||
// Attach config
|
||||
slip_modem->buffer_len = modem_config->rx_buffer_len;
|
||||
|
||||
slip_modem->rx_filter = modem_config->rx_filter;
|
||||
|
||||
slip_modem->uart.uart_dev = modem_config->uart_dev;
|
||||
slip_modem->uart.uart_baud = modem_config->uart_baud;
|
||||
slip_modem->uart.uart_rx_pin = modem_config->uart_rx_pin;
|
||||
slip_modem->uart.uart_tx_pin = modem_config->uart_tx_pin;
|
||||
memcpy(&slip_modem->addr, modem_config->ipv6_addr, sizeof(esp_ip6_addr_t));
|
||||
|
||||
// Return the new modem
|
||||
return slip_modem;
|
||||
}
|
||||
|
||||
// Internal handler called on driver start
|
||||
static esp_err_t esp_slip_driver_start(slip_modem_t *slip_modem)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s: Starting SLIP modem (modem %p)", __func__, slip_modem);
|
||||
|
||||
// Allocate RX buffer if one does not exist
|
||||
if (slip_modem->buffer == NULL) {
|
||||
slip_modem->buffer = malloc(slip_modem->buffer_len);
|
||||
}
|
||||
if (slip_modem->buffer == NULL) {
|
||||
ESP_LOGE(TAG, "error allocating rx buffer");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
// Build configuration
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = slip_modem->uart.uart_baud,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
};
|
||||
|
||||
// Initialise uart
|
||||
ESP_ERROR_CHECK(uart_param_config(slip_modem->uart.uart_dev, &uart_config));
|
||||
|
||||
// Set UART pins
|
||||
ESP_ERROR_CHECK(uart_set_pin(slip_modem->uart.uart_dev, slip_modem->uart.uart_tx_pin, slip_modem->uart.uart_rx_pin, 0, 0));
|
||||
|
||||
// Install UART driver
|
||||
ESP_ERROR_CHECK(uart_driver_install(slip_modem->uart.uart_dev, slip_modem->buffer_len, slip_modem->buffer_len, 10, &slip_modem->uart.uart_queue, 0));
|
||||
|
||||
// Start slip RX task
|
||||
slip_modem->running = true;
|
||||
xTaskCreate(slip_modem_uart_rx_task, "slip_modem_uart_rx_task", SLIP_RX_TASK_STACK_SIZE, slip_modem, SLIP_RX_TASK_PRIORITY, &slip_modem->uart.uart_rx_task);
|
||||
|
||||
// Finally, initialise slip network interface
|
||||
esp_netif_action_start(slip_modem->base.netif, 0, 0, 0);
|
||||
ESP_ERROR_CHECK(slip_modem_netif_start(slip_modem->base.netif, &slip_modem->addr));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t slip_modem_destroy(slip_modem_t *slip)
|
||||
{
|
||||
// Stop slip driver
|
||||
esp_netif_action_stop(slip->base.netif, 0, 0, 0);
|
||||
ESP_ERROR_CHECK(slip_modem_netif_stop(slip->base.netif));
|
||||
|
||||
// Stop uart rx task
|
||||
vTaskDelete(slip->uart.uart_rx_task);
|
||||
|
||||
// Delete driver
|
||||
uart_driver_delete(slip->uart.uart_dev);
|
||||
|
||||
// Free slip interface
|
||||
free(slip);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Modem transmit for glue logic
|
||||
static esp_err_t slip_modem_transmit(void *slip_driver, void *buffer, size_t len)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG);
|
||||
slip_modem_t *slip_modem = (slip_modem_t *) slip_driver;
|
||||
|
||||
int32_t res = uart_write_bytes(slip_modem->uart.uart_dev, (char *)buffer, len);
|
||||
if (res < 0) {
|
||||
// Handle errors
|
||||
ESP_LOGE(TAG, "%s: uart_write_bytes error %i", __func__, res);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Post-attach handler for netif
|
||||
static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args)
|
||||
{
|
||||
slip_modem_t *slip_modem = (slip_modem_t *) args;
|
||||
|
||||
ESP_LOGD(TAG, "%s (netif: %p args: %p)", __func__, esp_netif, args);
|
||||
|
||||
const esp_netif_driver_ifconfig_t driver_ifconfig = {
|
||||
.driver_free_rx_buffer = NULL,
|
||||
.transmit = slip_modem_transmit,
|
||||
.handle = slip_modem,
|
||||
};
|
||||
|
||||
slip_modem->base.netif = esp_netif;
|
||||
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
|
||||
|
||||
esp_slip_driver_start(slip_modem);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void slip_modem_uart_rx_task(void *arg)
|
||||
{
|
||||
slip_modem_t *slip_modem = (slip_modem_t *) arg;
|
||||
|
||||
ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p filter: %p)", slip_modem, slip_modem->rx_filter);
|
||||
ESP_LOGD(TAG, "Uart: %d, buffer: %p (%d bytes)", slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len);
|
||||
|
||||
while (slip_modem->running == true) {
|
||||
// Read data from the UART
|
||||
int len = uart_read_bytes(slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len, 1 / portTICK_PERIOD_MS);
|
||||
|
||||
if (len > 0) {
|
||||
|
||||
// Log slip RX data
|
||||
ESP_LOGD(TAG, "rx %d bytes", len);
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, slip_modem->buffer, len, ESP_LOG_DEBUG);
|
||||
|
||||
// Ensure null termination
|
||||
slip_modem->buffer[len] = '\0';
|
||||
|
||||
// Filter if provided
|
||||
if ((slip_modem->rx_filter != NULL) && slip_modem->rx_filter(slip_modem, slip_modem->buffer, len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Pass received bytes in to slip interface
|
||||
ESP_LOGI(TAG, "esp_netif %p", slip_modem->base.netif);
|
||||
esp_netif_receive(slip_modem->base.netif, slip_modem->buffer, len, NULL);
|
||||
}
|
||||
|
||||
// Yield to allow other tasks to progress
|
||||
vTaskDelay(1 * portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the internally configured ipv6 address
|
||||
*/
|
||||
esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip)
|
||||
{
|
||||
return slip->addr;
|
||||
}
|
||||
|
||||
void slip_modem_raw_write(slip_modem_t *slip, void *buffer, size_t len)
|
||||
{
|
||||
slip_modem_netif_raw_write(slip->base.netif, buffer, len);
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_netif.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif_net_stack.h"
|
||||
#include "lwip/esp_netif_net_stack.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "netif/slipif.h"
|
||||
#include "lwip/sio.h"
|
||||
|
||||
static const char *TAG = "slip-modem-netif";
|
||||
|
||||
/**
|
||||
* @brief Stops the SLIP interface
|
||||
*/
|
||||
esp_err_t slip_modem_netif_stop(esp_netif_t *esp_netif)
|
||||
{
|
||||
struct netif *netif = esp_netif_get_netif_impl(esp_netif);
|
||||
|
||||
ESP_LOGI(TAG, "%s: Stopped SLIP connection: lwip netif:%p", __func__, netif);
|
||||
|
||||
// Stop interface
|
||||
netif_set_link_down(netif);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the SLIP interface
|
||||
*/
|
||||
esp_err_t slip_modem_netif_start(esp_netif_t *esp_netif, esp_ip6_addr_t *addr)
|
||||
{
|
||||
struct netif *netif = esp_netif_get_netif_impl(esp_netif);
|
||||
|
||||
ESP_LOGI(TAG, "%s: Starting SLIP interface: lwip netif:%p", __func__, netif);
|
||||
|
||||
// Set the netif up
|
||||
netif_set_up(netif);
|
||||
netif_set_link_up(netif);
|
||||
#if CONFIG_LWIP_IPV6
|
||||
int8_t addr_index = 0;
|
||||
|
||||
netif_ip6_addr_set(netif, addr_index, (ip6_addr_t *)addr);
|
||||
netif_ip6_addr_set_state(netif, addr_index, IP6_ADDR_VALID);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write incoming serial data to the SLIP interface
|
||||
*/
|
||||
void esp_netif_lwip_slip_input(void *h, void *buffer, unsigned int len, void *eb)
|
||||
{
|
||||
struct netif *netif = h;
|
||||
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG);
|
||||
|
||||
// Update slip netif with data
|
||||
const int max_batch = 255;
|
||||
int sent = 0;
|
||||
while(sent < len) {
|
||||
int batch = (len - sent) > max_batch ? max_batch : (len - sent);
|
||||
slipif_received_bytes(netif, buffer+sent, batch);
|
||||
sent += batch;
|
||||
}
|
||||
|
||||
// Process incoming bytes
|
||||
for (int i = 0; i < len; i++) {
|
||||
slipif_process_rxqueue(netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write raw data out the SLIP interface
|
||||
*/
|
||||
void slip_modem_netif_raw_write(esp_netif_t *netif, void *buffer, size_t len)
|
||||
{
|
||||
struct netif *lwip_netif = esp_netif_get_netif_impl(netif);
|
||||
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
|
||||
struct pbuf p = {
|
||||
.next = NULL,
|
||||
.payload = buffer,
|
||||
.tot_len = len,
|
||||
.len = len,
|
||||
};
|
||||
|
||||
// Call slip if output function to feed data out slip interface
|
||||
#if CONFIG_LWIP_IPV6
|
||||
lwip_netif->output_ip6(lwip_netif, &p, NULL);
|
||||
#else
|
||||
lwip_netif->output(lwip_netif, &p, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** @brief Get esp-netif object corresponding to registration index
|
||||
*/
|
||||
static esp_netif_t * get_netif_with_esp_index(int index)
|
||||
{
|
||||
esp_netif_t *netif = NULL;
|
||||
int counter = 0;
|
||||
while ((netif = esp_netif_next(netif)) != NULL) {
|
||||
if (counter == index) {
|
||||
return netif;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @brief Return list registration index of the supplied netif ptr
|
||||
*/
|
||||
static int get_esp_netif_index(esp_netif_t * esp_netif)
|
||||
{
|
||||
esp_netif_t *netif = NULL;
|
||||
int counter = 0;
|
||||
while ((netif = esp_netif_next(netif)) != NULL) {
|
||||
if (esp_netif == netif) {
|
||||
return counter;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
err_t esp_slipif_init(struct netif *netif)
|
||||
{
|
||||
esp_netif_t *esp_netif = netif->state;
|
||||
int esp_index = get_esp_netif_index(esp_netif);
|
||||
if (esp_index < 0) {
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
// Store netif index in net interface for SIO open command to abstract the dev
|
||||
netif->state = (void *)esp_index;
|
||||
|
||||
return slipif_init(netif);
|
||||
}
|
||||
|
||||
const struct esp_netif_netstack_config s_netif_config_slip = {
|
||||
.lwip = {
|
||||
.init_fn = esp_slipif_init,
|
||||
.input_fn = esp_netif_lwip_slip_input,
|
||||
}
|
||||
};
|
||||
|
||||
const esp_netif_netstack_config_t *netstack_default_slip = &s_netif_config_slip;
|
||||
|
||||
|
||||
/***
|
||||
* @brief Open a serial device for communication
|
||||
*/
|
||||
sio_fd_t sio_open(uint8_t devnum)
|
||||
{
|
||||
ESP_LOGD(TAG, "Opening device: %d\r\n", devnum);
|
||||
|
||||
esp_netif_t *esp_netif = get_netif_with_esp_index(devnum);
|
||||
if (!esp_netif) {
|
||||
ESP_LOGE(TAG, "didn't find esp-netif with index=%d\n", devnum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return SIO handle
|
||||
return esp_netif;
|
||||
}
|
||||
|
||||
/***
|
||||
* @brief Send a single character to the serial device (blocking)
|
||||
*/
|
||||
void sio_send(uint8_t c, sio_fd_t fd)
|
||||
{
|
||||
esp_netif_t *esp_netif = fd;
|
||||
|
||||
ESP_LOGD(TAG, "%s", __func__);
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, &c, 1, ESP_LOG_DEBUG);
|
||||
|
||||
esp_err_t ret = esp_netif_transmit(esp_netif, &c, 1);
|
||||
if (ret != ESP_OK) {
|
||||
// Handle errors
|
||||
ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, ret);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Stop the esp slip netif
|
||||
*
|
||||
* @param[in] esp_netif handle to slip esp-netif instance
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t slip_modem_netif_stop(esp_netif_t *esp_netif);
|
||||
|
||||
/**
|
||||
* @brief Start the esp slip netif
|
||||
*
|
||||
* @param[in] esp_netif handle to slip esp-netif instance
|
||||
* @param[in] addr IPv6 address associated with this SLIP interface
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t slip_modem_netif_start(esp_netif_t *esp_netif, esp_ip6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Data path API to write raw packet ous the SLIP interface
|
||||
*
|
||||
* This API is typically used when implementing user defined methods
|
||||
*
|
||||
* @param[in] esp_netif handle to slip esp-netif instance
|
||||
* @param[in] buffer pointer to the outgoing data
|
||||
* @param[in] len length of the data
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
void slip_modem_netif_raw_write(esp_netif_t *netif, void *buffer, size_t len);
|
Reference in New Issue
Block a user