mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-17 20:42:21 +02:00
Test: Initial version of modem tests
This commit is contained in:
@ -1,18 +1,31 @@
|
|||||||
set(srcs "src/esp_modem_dte.cpp"
|
idf_build_get_property(target IDF_TARGET)
|
||||||
|
|
||||||
|
if(${target} STREQUAL "linux")
|
||||||
|
set(platform_srcs src/esp_modem_primitives_linux.cpp
|
||||||
|
src/esp_modem_uart_linux.cpp
|
||||||
|
src/esp_modem_netif_linux.cpp)
|
||||||
|
set(dependencies esp_system_protocols_linux)
|
||||||
|
else()
|
||||||
|
set(platform_srcs src/esp_modem_primitives_freertos.cpp
|
||||||
|
src/esp_modem_uart.cpp
|
||||||
|
src/esp_modem_netif.cpp)
|
||||||
|
set(dependencies driver)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(srcs ${platform_srcs}
|
||||||
|
"src/esp_modem_dte.cpp"
|
||||||
"src/esp_modem_dce.cpp"
|
"src/esp_modem_dce.cpp"
|
||||||
"src/esp_modem_netif.cpp"
|
|
||||||
"src/esp_modem_api.cpp"
|
"src/esp_modem_api.cpp"
|
||||||
"src/esp_modem_factory.cpp"
|
"src/esp_modem_factory.cpp"
|
||||||
"src/esp_modem_cmux.cpp"
|
"src/esp_modem_cmux.cpp"
|
||||||
"src/esp_modem_command_library.cpp"
|
"src/esp_modem_command_library.cpp"
|
||||||
"src/esp_modem_modules.cpp"
|
"src/esp_modem_modules.cpp")
|
||||||
"src/esp_modem_uart.cpp")
|
|
||||||
|
|
||||||
set(include_dirs "include")
|
set(include_dirs "include")
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS "${include_dirs}"
|
INCLUDE_DIRS "${include_dirs}"
|
||||||
PRIV_INCLUDE_DIRS private_include
|
PRIV_INCLUDE_DIRS private_include
|
||||||
REQUIRES driver)
|
REQUIRES ${dependencies})
|
||||||
|
|
||||||
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
||||||
|
@ -58,9 +58,10 @@ public:
|
|||||||
return dte->command(command, std::move(got_line), time_ms);
|
return dte->command(command, std::move(got_line), time_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
bool set_mode(modem_mode m) { return mode.set(dte.get(), module.get(), netif, m); }
|
bool set_mode(modem_mode m) { return mode.set(dte.get(), module.get(), netif, m); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<DTE> dte;
|
std::shared_ptr<DTE> dte;
|
||||||
std::shared_ptr<SpecificModule> module;
|
std::shared_ptr<SpecificModule> module;
|
||||||
|
@ -50,12 +50,12 @@ template<typename Module>
|
|||||||
class Builder {
|
class Builder {
|
||||||
static_assert(std::is_base_of<ModuleIf, Module>::value, "Builder must be used only for Module classes");
|
static_assert(std::is_base_of<ModuleIf, Module>::value, "Builder must be used only for Module classes");
|
||||||
public:
|
public:
|
||||||
explicit Builder(std::shared_ptr<DTE> dte): dte(std::move(dte))
|
// explicit Builder(std::shared_ptr<DTE> dte): dte(std::move(dte))
|
||||||
{
|
// {
|
||||||
esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_PPP();
|
// esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
netif = esp_netif_new(&netif_config);
|
// netif = esp_netif_new(&netif_config);
|
||||||
throw_if_false(netif != nullptr, "Cannot create default PPP netif");
|
// throw_if_false(netif != nullptr, "Cannot create default PPP netif");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Builder(std::shared_ptr<DTE> x, esp_netif_t* esp_netif): dte(std::move(x)), module(nullptr), netif(esp_netif)
|
Builder(std::shared_ptr<DTE> x, esp_netif_t* esp_netif): dte(std::move(x)), module(nullptr), netif(esp_netif)
|
||||||
{
|
{
|
||||||
|
@ -69,7 +69,7 @@ private:
|
|||||||
|
|
||||||
void setup_cmux();
|
void setup_cmux();
|
||||||
|
|
||||||
static const size_t GOT_LINE = BIT0;
|
static const size_t GOT_LINE = signal_group::bit0;
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
size_t consumed;
|
size_t consumed;
|
||||||
std::unique_ptr<uint8_t[]> buffer;
|
std::unique_ptr<uint8_t[]> buffer;
|
||||||
|
66
esp_modem/include/cxx_include/esp_modem_exception.hpp
Normal file
66
esp_modem/include/cxx_include/esp_modem_exception.hpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef _ESP_MODEM_EXCEPTION_HPP_
|
||||||
|
#define _ESP_MODEM_EXCEPTION_HPP_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
namespace esp_modem {
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||||
|
#define THROW(exception) throw(exception)
|
||||||
|
class esp_err_exception: virtual public std::exception {
|
||||||
|
public:
|
||||||
|
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
|
||||||
|
explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {}
|
||||||
|
explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {}
|
||||||
|
virtual esp_err_t get_err_t() { return esp_err; }
|
||||||
|
~esp_err_exception() noexcept override = default;
|
||||||
|
virtual const char* what() const noexcept {
|
||||||
|
return message.c_str();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
esp_err_t esp_err;
|
||||||
|
std::string message;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#define THROW(exception) abort()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void throw_if_false(bool condition, std::string message)
|
||||||
|
{
|
||||||
|
if (!condition) {
|
||||||
|
THROW(esp_err_exception(std::move(message)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void throw_if_esp_fail(esp_err_t err, std::string message)
|
||||||
|
{
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
THROW(esp_err_exception(std::move(message), err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void throw_if_esp_fail(esp_err_t err)
|
||||||
|
{
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
THROW(esp_err_exception(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esp_modem
|
||||||
|
|
||||||
|
#endif //_ESP_MODEM_EXCEPTION_HPP_
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef _ESP_MODEM_NETIF_HPP
|
#ifndef _ESP_MODEM_NETIF_HPP
|
||||||
#define _ESP_MODEM_NETIF_HPP
|
#define _ESP_MODEM_NETIF_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cstddef>
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "cxx_include/esp_modem_primitives.hpp"
|
#include "cxx_include/esp_modem_primitives.hpp"
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ public:
|
|||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
void wait_until_ppp_exits() { signal.wait(PPP_EXIT, 30000); }
|
void wait_until_ppp_exits();
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
@ -53,8 +55,8 @@ private:
|
|||||||
esp_netif_t *netif;
|
esp_netif_t *netif;
|
||||||
struct ppp_netif_driver driver{};
|
struct ppp_netif_driver driver{};
|
||||||
signal_group signal;
|
signal_group signal;
|
||||||
static const size_t PPP_STARTED = BIT0;
|
static const size_t PPP_STARTED = signal_group::bit0;
|
||||||
static const size_t PPP_EXIT = BIT1;
|
static const size_t PPP_EXIT = signal_group::bit1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace esp_modem
|
} // namespace esp_modem
|
||||||
|
@ -14,116 +14,73 @@
|
|||||||
|
|
||||||
#ifndef _ESP_MODEM_PRIMITIVES_HPP_
|
#ifndef _ESP_MODEM_PRIMITIVES_HPP_
|
||||||
#define _ESP_MODEM_PRIMITIVES_HPP_
|
#define _ESP_MODEM_PRIMITIVES_HPP_
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "esp_modem_exception.hpp"
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "freertos/semphr.h"
|
#if defined(CONFIG_IDF_TARGET_LINUX)
|
||||||
|
#include <mutex>
|
||||||
|
#else
|
||||||
|
// forward declarations of FreeRTOS primitives
|
||||||
|
struct QueueDefinition;
|
||||||
|
typedef void * EventGroupHandle_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace esp_modem {
|
namespace esp_modem {
|
||||||
|
|
||||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
#if !defined(CONFIG_IDF_TARGET_LINUX)
|
||||||
#define THROW(exception) throw(exception)
|
|
||||||
class esp_err_exception: virtual public std::exception {
|
|
||||||
public:
|
|
||||||
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
|
|
||||||
explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {}
|
|
||||||
explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {}
|
|
||||||
virtual esp_err_t get_err_t() { return esp_err; }
|
|
||||||
~esp_err_exception() noexcept override = default;
|
|
||||||
virtual const char* what() const noexcept {
|
|
||||||
return message.c_str();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
esp_err_t esp_err;
|
|
||||||
std::string message;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#define THROW(exception) abort()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void throw_if_false(bool condition, std::string message)
|
|
||||||
{
|
|
||||||
if (!condition) {
|
|
||||||
THROW(esp_err_exception(std::move(message)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void throw_if_esp_fail(esp_err_t err, std::string message)
|
|
||||||
{
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
THROW(esp_err_exception(std::move(message), err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void throw_if_esp_fail(esp_err_t err)
|
|
||||||
{
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
THROW(esp_err_exception(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Lock {
|
struct Lock {
|
||||||
explicit Lock(): lock(nullptr)
|
using MutexT = QueueDefinition*;
|
||||||
{
|
|
||||||
lock = xSemaphoreCreateRecursiveMutex();
|
|
||||||
throw_if_false(lock != nullptr, "create signal event group failed");
|
|
||||||
}
|
|
||||||
~Lock() { vSemaphoreDelete(lock); }
|
|
||||||
void take() { xSemaphoreTakeRecursive(lock, portMAX_DELAY); }
|
|
||||||
|
|
||||||
void give() { xSemaphoreGiveRecursive(lock); }
|
explicit Lock();
|
||||||
xSemaphoreHandle lock;
|
~Lock();
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
private:
|
||||||
|
MutexT m{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Signal = void*;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using Lock = std::mutex;
|
||||||
|
struct SignalGroup;
|
||||||
|
using Signal = std::unique_ptr<SignalGroup>;
|
||||||
|
#endif
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class Scoped {
|
class Scoped {
|
||||||
public:
|
public:
|
||||||
explicit Scoped(T &l):lock(l) { lock.take(); }
|
explicit Scoped(T &l):lock(l) { lock.lock(); }
|
||||||
~Scoped() { lock.give(); }
|
~Scoped() { lock.unlock(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T& lock;
|
T& lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct signal_group {
|
struct signal_group {
|
||||||
explicit signal_group(): event_group(nullptr)
|
static constexpr size_t bit0 = 1 << 0;
|
||||||
{
|
static constexpr size_t bit1 = 1 << 1;
|
||||||
event_group = xEventGroupCreate();
|
static constexpr size_t bit2 = 1 << 2;
|
||||||
throw_if_false(event_group != nullptr, "create signal event group failed");
|
static constexpr size_t bit3 = 1 << 3;
|
||||||
}
|
|
||||||
|
|
||||||
void set(uint32_t bits)
|
explicit signal_group();
|
||||||
{
|
|
||||||
xEventGroupSetBits(event_group, bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear(uint32_t bits)
|
void set(uint32_t bits);
|
||||||
{
|
|
||||||
xEventGroupClearBits(event_group, bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wait(uint32_t flags, uint32_t time_ms) // waiting for all and clearing if set
|
void clear(uint32_t bits);
|
||||||
{
|
|
||||||
EventBits_t bits = xEventGroupWaitBits(event_group, flags, pdTRUE, pdTRUE, pdMS_TO_TICKS(time_ms));
|
|
||||||
return bits & flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_any(uint32_t flags)
|
// waiting for all and clearing if set
|
||||||
{
|
bool wait(uint32_t flags, uint32_t time_ms);
|
||||||
return xEventGroupGetBits(event_group) & flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wait_any(uint32_t flags, uint32_t time_ms) // waiting for any bit, not clearing them
|
bool is_any(uint32_t flags);
|
||||||
{
|
|
||||||
EventBits_t bits = xEventGroupWaitBits(event_group, flags, pdFALSE, pdFALSE, pdMS_TO_TICKS(time_ms));
|
|
||||||
return bits & flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
~signal_group()
|
// waiting for any bit, not clearing them
|
||||||
{
|
bool wait_any(uint32_t flags, uint32_t time_ms);
|
||||||
if (event_group) vEventGroupDelete(event_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventGroupHandle_t event_group;
|
~signal_group();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Signal event_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace esp_modem
|
} // namespace esp_modem
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include "cxx_include/esp_modem_dte.hpp"
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
#include "uart_terminal.hpp"
|
#include "uart_terminal.hpp"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <unistd.h>
|
||||||
#include "cxx_include/esp_modem_dte.hpp"
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ void CMUXedTerminal::start()
|
|||||||
for (size_t i = 0; i < 3; i++)
|
for (size_t i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
send_sabm(i);
|
send_sabm(i);
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS); // Waiting before open next DLC
|
usleep(100'000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,13 +111,13 @@ bool CMUXedTerminal::process_cmux_recv(size_t len)
|
|||||||
|
|
||||||
bool output(uint8_t *data, size_t len, std::string message)
|
bool output(uint8_t *data, size_t len, std::string message)
|
||||||
{
|
{
|
||||||
printf("OUTPUT: %s len=%d \n", message.c_str(), len);
|
// printf("OUTPUT: %s len=%ld \n", message.c_str(), len);
|
||||||
for (int i=0; i< len; ++i) {
|
for (int i=0; i< len; ++i) {
|
||||||
printf("0x%02x, ",data[i]);
|
printf("0x%02x, ",data[i]);
|
||||||
}
|
}
|
||||||
printf("----\n");
|
printf("----\n");
|
||||||
|
|
||||||
printf("%.*s", len, data);
|
printf("%.*s", (int)len, data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +220,7 @@ void CMUXedTerminal::setup_cmux()
|
|||||||
for (size_t i = 0; i < 3; i++)
|
for (size_t i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
send_sabm(i);
|
send_sabm(i);
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS); // Waiting before open next DLC
|
usleep(100'000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,8 +236,6 @@ void DTE::setup_cmux()
|
|||||||
|
|
||||||
void DTE::send_cmux_command(uint8_t i, const std::string& command)
|
void DTE::send_cmux_command(uint8_t i, const std::string& command)
|
||||||
{
|
{
|
||||||
// send_sabm(i);
|
|
||||||
// vTaskDelay(100 / portTICK_PERIOD_MS); // Waiting before open next DLC
|
|
||||||
|
|
||||||
uint8_t frame[6];
|
uint8_t frame[6];
|
||||||
frame[0] = SOF_MARKER;
|
frame[0] = SOF_MARKER;
|
||||||
|
@ -29,7 +29,6 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
|
|||||||
{
|
{
|
||||||
Scoped<Lock> l(lock);
|
Scoped<Lock> l(lock);
|
||||||
command_result res = command_result::TIMEOUT;
|
command_result res = command_result::TIMEOUT;
|
||||||
term->write((uint8_t *)command.c_str(), command.length());
|
|
||||||
term->set_data_cb([&](size_t len){
|
term->set_data_cb([&](size_t len){
|
||||||
auto data_to_read = std::min(len, buffer_size - consumed);
|
auto data_to_read = std::min(len, buffer_size - consumed);
|
||||||
auto data = buffer.get() + consumed;
|
auto data = buffer.get() + consumed;
|
||||||
@ -44,6 +43,7 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
term->write((uint8_t *)command.c_str(), command.length());
|
||||||
auto got_lf = signal.wait(GOT_LINE, time_ms);
|
auto got_lf = signal.wait(GOT_LINE, time_ms);
|
||||||
if (got_lf && res == command_result::TIMEOUT) {
|
if (got_lf && res == command_result::TIMEOUT) {
|
||||||
throw_if_esp_fail(ESP_ERR_INVALID_STATE);
|
throw_if_esp_fail(ESP_ERR_INVALID_STATE);
|
||||||
|
@ -53,7 +53,7 @@ esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) {
|
|||||||
// check if PPP error events are enabled, if not, do enable the error occurred/state changed
|
// check if PPP error events are enabled, if not, do enable the error occurred/state changed
|
||||||
// to notify the modem layer when switching modes
|
// to notify the modem layer when switching modes
|
||||||
esp_netif_ppp_config_t ppp_config;
|
esp_netif_ppp_config_t ppp_config;
|
||||||
esp_netif_ppp_get_params(esp_netif, &ppp_config);
|
// esp_netif_ppp_get_params(esp_netif, &ppp_config);
|
||||||
if (!ppp_config.ppp_error_event_enabled) {
|
if (!ppp_config.ppp_error_event_enabled) {
|
||||||
ppp_config.ppp_error_event_enabled = true;
|
ppp_config.ppp_error_event_enabled = true;
|
||||||
esp_netif_ppp_set_params(esp_netif, &ppp_config);
|
esp_netif_ppp_set_params(esp_netif, &ppp_config);
|
||||||
@ -102,4 +102,8 @@ Netif::~Netif() {
|
|||||||
esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected);
|
esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Netif::wait_until_ppp_exits() {
|
||||||
|
signal.wait(PPP_EXIT, 30000);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace esp_modem
|
} // namespace esp_modem
|
51
esp_modem/src/esp_modem_netif_linux.cpp
Normal file
51
esp_modem/src/esp_modem_netif_linux.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "cxx_include/esp_modem_netif.hpp"
|
||||||
|
|
||||||
|
namespace esp_modem {
|
||||||
|
|
||||||
|
void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netif::receive(uint8_t *data, size_t len) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) :
|
||||||
|
ppp_dte(std::move(e)), netif(ppp_netif) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netif::start() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netif::stop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Netif::~Netif() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netif::wait_until_ppp_exits() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esp_modem
|
84
esp_modem/src/esp_modem_primitives_freertos.cpp
Normal file
84
esp_modem/src/esp_modem_primitives_freertos.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "cxx_include/esp_modem_primitives.hpp"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace esp_modem {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Lock::unlock() {
|
||||||
|
xSemaphoreGiveRecursive(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock::Lock(): m(nullptr)
|
||||||
|
{
|
||||||
|
m = xSemaphoreCreateRecursiveMutex();
|
||||||
|
throw_if_false(m != nullptr, "create signal event group failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock::~Lock() {
|
||||||
|
vSemaphoreDelete(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lock::lock() {
|
||||||
|
xSemaphoreTakeRecursive(m, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
signal_group::signal_group(): event_group(nullptr)
|
||||||
|
{
|
||||||
|
event_group = xEventGroupCreate();
|
||||||
|
throw_if_false(event_group != nullptr, "create signal event group failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void signal_group::set(uint32_t bits)
|
||||||
|
{
|
||||||
|
xEventGroupSetBits(event_group, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
void signal_group::clear(uint32_t bits)
|
||||||
|
{
|
||||||
|
xEventGroupClearBits(event_group, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool signal_group::wait(uint32_t flags, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(event_group, flags, pdTRUE, pdTRUE, pdMS_TO_TICKS(time_ms));
|
||||||
|
return bits & flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool signal_group::is_any(uint32_t flags)
|
||||||
|
{
|
||||||
|
return xEventGroupGetBits(event_group) & flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool signal_group::wait_any(uint32_t flags, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(event_group, flags, pdFALSE, pdFALSE, pdMS_TO_TICKS(time_ms));
|
||||||
|
return bits & flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
signal_group::~signal_group()
|
||||||
|
{
|
||||||
|
if (event_group) vEventGroupDelete(event_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esp_modem
|
72
esp_modem/src/esp_modem_primitives_linux.cpp
Normal file
72
esp_modem/src/esp_modem_primitives_linux.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include "cxx_include/esp_modem_primitives.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace esp_modem {
|
||||||
|
|
||||||
|
struct SignalGroup {
|
||||||
|
std::condition_variable notify;
|
||||||
|
std::mutex m;
|
||||||
|
uint32_t flags{ 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
signal_group::signal_group(): event_group(std::make_unique<SignalGroup>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void signal_group::set(uint32_t bits)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
event_group->flags |= bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void signal_group::clear(uint32_t bits)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
event_group->flags &= ~bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool signal_group::wait(uint32_t flags, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&]{
|
||||||
|
if ((flags&event_group->flags) == flags) {
|
||||||
|
event_group->flags &= ~flags;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
// return ret != std::cv_status::timeout;
|
||||||
|
// , [&]{return flags&event_group->flags; });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool signal_group::is_any(uint32_t flags)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
return flags&event_group->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool signal_group::wait_any(uint32_t flags, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(event_group->m);
|
||||||
|
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&]{ return flags&event_group->flags; });
|
||||||
|
}
|
||||||
|
|
||||||
|
signal_group::~signal_group() = default;
|
||||||
|
|
||||||
|
} // namespace esp_modem
|
15
esp_modem/src/esp_modem_uart_linux.cpp
Normal file
15
esp_modem/src/esp_modem_uart_linux.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
16
esp_modem/test/host_test/CMakeLists.txt
Normal file
16
esp_modem/test/host_test/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
|
||||||
|
set(EXTRA_COMPONENT_DIRS ../..)
|
||||||
|
|
||||||
|
set(COMPONENTS main)
|
||||||
|
project(host_modem_test)
|
||||||
|
|
||||||
|
|
||||||
|
idf_component_get_property(esp_modem esp_modem COMPONENT_LIB)
|
||||||
|
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_COMPILER_CXX_EXCEPTIONS")
|
||||||
|
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")
|
||||||
|
target_link_options(${esp_modem} INTERFACE -fsanitize=address)
|
||||||
|
#set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
|
||||||
|
#set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
|
@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS esp_event_mock.c
|
||||||
|
INCLUDE_DIRS include
|
||||||
|
REQUIRES esp_system_protocols_linux)
|
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/11/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char * WIFI_EVENT = "WIFI_EVENT";
|
||||||
|
const char * IP_EVENT = "IP_EVENT";
|
||||||
|
|
||||||
|
esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg)
|
||||||
|
{
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler)
|
||||||
|
{
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/9/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MDNS_HOST_ESP_EVENT_H
|
||||||
|
#define MDNS_HOST_ESP_EVENT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "esp_netif_ip_addr.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef void * esp_event_base_t;
|
||||||
|
typedef void * system_event_t;
|
||||||
|
|
||||||
|
extern const char * WIFI_EVENT;
|
||||||
|
extern const char * IP_EVENT;
|
||||||
|
|
||||||
|
#define ESP_EVENT_ANY_BASE NULL /**< register handler for any event base */
|
||||||
|
#define ESP_EVENT_ANY_ID -1 /**< register handler for any event id */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
|
||||||
|
esp_netif_t *esp_netif; /*!< Pointer to corresponding esp-netif object */
|
||||||
|
esp_netif_ip6_info_t ip6_info; /*!< IPv6 address of the interface */
|
||||||
|
int ip_index; /*!< IPv6 address index */
|
||||||
|
} ip_event_got_ip6_t;
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg);
|
||||||
|
|
||||||
|
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler);
|
||||||
|
|
||||||
|
#endif //MDNS_HOST_ESP_EVENT_H
|
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/9/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MDNS_HOST_ESP_EVENT_BASE_H
|
||||||
|
#define MDNS_HOST_ESP_EVENT_BASE_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
|
||||||
|
WIFI_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
|
||||||
|
WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */
|
||||||
|
WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
|
||||||
|
IP_EVENT_STA_GOT_IP,
|
||||||
|
IP_EVENT_GOT_IP6
|
||||||
|
} mdns_used_event_t;
|
||||||
|
|
||||||
|
#endif //MDNS_HOST_ESP_EVENT_BASE_H
|
@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS esp_netif_linux.c
|
||||||
|
INCLUDE_DIRS include
|
||||||
|
REQUIRES esp_system_protocols_linux)
|
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/7/21.
|
||||||
|
//
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include<string.h> //strlen
|
||||||
|
#include<sys/socket.h>
|
||||||
|
#include<arpa/inet.h> //inet_addr
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
|
||||||
|
{
|
||||||
|
ESP_IPADDR4_INIT(&ip_info->ip, 1,2,3,4);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
|
||||||
|
{
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ifaddrs *addrs, *tmp;
|
||||||
|
getifaddrs(&addrs);
|
||||||
|
tmp = addrs;
|
||||||
|
|
||||||
|
while (tmp)
|
||||||
|
{
|
||||||
|
// if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET)
|
||||||
|
// {
|
||||||
|
// struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
|
||||||
|
// printf("%s: %s\n", tmp->ifa_name, inet_ntoa(pAddr->sin_addr));
|
||||||
|
// } else
|
||||||
|
|
||||||
|
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) {
|
||||||
|
char addr[64];
|
||||||
|
struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
|
inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) );
|
||||||
|
printf("%s: %s\n", tmp->ifa_name, addr);
|
||||||
|
inet6_addr_to_ip6addr(if_ip6, &pAddr->sin6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = tmp->ifa_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeifaddrs(addrs);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
|
||||||
|
{
|
||||||
|
char * ifname = "enp1s0";
|
||||||
|
uint32_t interfaceIndex = if_nametoindex(ifname);
|
||||||
|
printf("%s: %d\n", ifname, interfaceIndex);
|
||||||
|
return interfaceIndex;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef _HOST_ESP_NETIF_H_
|
||||||
|
#define _HOST_ESP_NETIF_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp_netif_ip_addr.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
struct esp_netif_obj {};
|
||||||
|
|
||||||
|
typedef struct esp_netif_driver_base_s {
|
||||||
|
esp_err_t (*post_attach)(esp_netif_t *netif, void* h);
|
||||||
|
esp_netif_t *netif;
|
||||||
|
} esp_netif_driver_base_t;
|
||||||
|
|
||||||
|
struct esp_netif_driver_ifconfig {
|
||||||
|
void* handle;
|
||||||
|
esp_err_t (*transmit)(void *h, void *buffer, size_t len);
|
||||||
|
esp_err_t (*transmit_wrap)(void *h, void *buffer, size_t len, void *netstack_buffer);
|
||||||
|
void (*driver_free_rx_buffer)(void *h, void* buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct esp_netif_obj esp_netif_t;
|
||||||
|
|
||||||
|
/** @brief Status of DHCP client or DHCP server */
|
||||||
|
typedef enum {
|
||||||
|
ESP_NETIF_DHCP_INIT = 0, /**< DHCP client/server is in initial state (not yet started) */
|
||||||
|
ESP_NETIF_DHCP_STARTED, /**< DHCP client/server has been started */
|
||||||
|
ESP_NETIF_DHCP_STOPPED, /**< DHCP client/server has been stopped */
|
||||||
|
ESP_NETIF_DHCP_STATUS_MAX
|
||||||
|
} esp_netif_dhcp_status_t;
|
||||||
|
|
||||||
|
|
||||||
|
esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key);
|
||||||
|
|
||||||
|
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info);
|
||||||
|
|
||||||
|
esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status);
|
||||||
|
|
||||||
|
esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6);
|
||||||
|
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif);
|
||||||
|
|
||||||
|
void esp_netif_action_connected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||||
|
void esp_netif_action_disconnected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||||
|
|
||||||
|
#endif // _HOST_ESP_NETIF_H_
|
@ -0,0 +1,182 @@
|
|||||||
|
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef _ESP_NETIF_IP_ADDR_H_
|
||||||
|
#define _ESP_NETIF_IP_ADDR_H_
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
#define esp_netif_htonl(x) ((uint32_t)(x))
|
||||||
|
#else
|
||||||
|
#define esp_netif_htonl(x) ((((x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||||
|
(((x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||||
|
(((x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||||
|
(((x) & (uint32_t)0xff000000UL) >> 24))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define esp_netif_ip4_makeu32(a,b,c,d) (((uint32_t)((a) & 0xff) << 24) | \
|
||||||
|
((uint32_t)((b) & 0xff) << 16) | \
|
||||||
|
((uint32_t)((c) & 0xff) << 8) | \
|
||||||
|
(uint32_t)((d) & 0xff))
|
||||||
|
|
||||||
|
// Access address in 16-bit block
|
||||||
|
#define ESP_IP6_ADDR_BLOCK1(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[0]) >> 16) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK2(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[0])) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK3(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[1]) >> 16) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK4(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[1])) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK5(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[2]) >> 16) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK6(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[2])) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK7(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[3]) >> 16) & 0xffff))
|
||||||
|
#define ESP_IP6_ADDR_BLOCK8(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[3])) & 0xffff))
|
||||||
|
|
||||||
|
#define IPSTR "%d.%d.%d.%d"
|
||||||
|
#define esp_ip4_addr_get_byte(ipaddr, idx) (((const uint8_t*)(&(ipaddr)->addr))[idx])
|
||||||
|
#define esp_ip4_addr1(ipaddr) esp_ip4_addr_get_byte(ipaddr, 0)
|
||||||
|
#define esp_ip4_addr2(ipaddr) esp_ip4_addr_get_byte(ipaddr, 1)
|
||||||
|
#define esp_ip4_addr3(ipaddr) esp_ip4_addr_get_byte(ipaddr, 2)
|
||||||
|
#define esp_ip4_addr4(ipaddr) esp_ip4_addr_get_byte(ipaddr, 3)
|
||||||
|
|
||||||
|
|
||||||
|
#define esp_ip4_addr1_16(ipaddr) ((uint16_t)esp_ip4_addr1(ipaddr))
|
||||||
|
#define esp_ip4_addr2_16(ipaddr) ((uint16_t)esp_ip4_addr2(ipaddr))
|
||||||
|
#define esp_ip4_addr3_16(ipaddr) ((uint16_t)esp_ip4_addr3(ipaddr))
|
||||||
|
#define esp_ip4_addr4_16(ipaddr) ((uint16_t)esp_ip4_addr4(ipaddr))
|
||||||
|
|
||||||
|
#define IP2STR(ipaddr) esp_ip4_addr1_16(ipaddr), \
|
||||||
|
esp_ip4_addr2_16(ipaddr), \
|
||||||
|
esp_ip4_addr3_16(ipaddr), \
|
||||||
|
esp_ip4_addr4_16(ipaddr)
|
||||||
|
|
||||||
|
#define IPV6STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
|
||||||
|
|
||||||
|
#define IPV62STR(ipaddr) ESP_IP6_ADDR_BLOCK1(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK2(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK3(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK4(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK5(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK6(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK7(&(ipaddr)), \
|
||||||
|
ESP_IP6_ADDR_BLOCK8(&(ipaddr))
|
||||||
|
|
||||||
|
#define ESP_IPADDR_TYPE_V4 0U
|
||||||
|
#define ESP_IPADDR_TYPE_V6 6U
|
||||||
|
#define ESP_IPADDR_TYPE_ANY 46U
|
||||||
|
|
||||||
|
#define ESP_IP4TOUINT32(a,b,c,d) (((uint32_t)((a) & 0xffU) << 24) | \
|
||||||
|
((uint32_t)((b) & 0xffU) << 16) | \
|
||||||
|
((uint32_t)((c) & 0xffU) << 8) | \
|
||||||
|
(uint32_t)((d) & 0xffU))
|
||||||
|
|
||||||
|
#define ESP_IP4TOADDR(a,b,c,d) esp_netif_htonl(ESP_IP4TOUINT32(a, b, c, d))
|
||||||
|
|
||||||
|
// new definitions
|
||||||
|
#define ESP_IPADDR4_INIT(ipaddr, a,b,c,d) (ipaddr)->addr = ESP_IP4TOADDR(a,b,c,d)
|
||||||
|
#define ESP_IP6TOADDR(a, b, c, d) { { { { a, b, c, d } , 0 } }, ESP_IPADDR_TYPE_V6 }
|
||||||
|
|
||||||
|
// TODO: use esp-netif instead of lwip API
|
||||||
|
#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6))
|
||||||
|
#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4))
|
||||||
|
#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0)
|
||||||
|
#define IP_GET_TYPE(ipaddr) ((ipaddr)->type)
|
||||||
|
#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == ESP_IPADDR_TYPE_V6)
|
||||||
|
#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
|
||||||
|
#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \
|
||||||
|
(dest).addr[1] = (src).addr[1]; \
|
||||||
|
(dest).addr[2] = (src).addr[2]; \
|
||||||
|
(dest).addr[3] = (src).addr[3];}while(0)
|
||||||
|
|
||||||
|
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
|
||||||
|
ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \
|
||||||
|
ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
#define IP_MULTICAST(a) IN_CLASSD(a)
|
||||||
|
|
||||||
|
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & htonl(0xff000000UL)) == htonl(0xff000000UL))
|
||||||
|
#define IP6_NO_ZONE 0
|
||||||
|
#define ip6_addr_clear_zone(ip6addr) ((ip6addr)->zone = IP6_NO_ZONE)
|
||||||
|
|
||||||
|
#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s6_addr32[0] = (source_ip6addr)->addr[0]; \
|
||||||
|
(target_in6addr)->s6_addr32[1] = (source_ip6addr)->addr[1]; \
|
||||||
|
(target_in6addr)->s6_addr32[2] = (source_ip6addr)->addr[2]; \
|
||||||
|
(target_in6addr)->s6_addr32[3] = (source_ip6addr)->addr[3];}
|
||||||
|
|
||||||
|
#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s6_addr32[0]; \
|
||||||
|
(target_ip6addr)->addr[1] = (source_in6addr)->s6_addr32[1]; \
|
||||||
|
(target_ip6addr)->addr[2] = (source_in6addr)->s6_addr32[2]; \
|
||||||
|
(target_ip6addr)->addr[3] = (source_in6addr)->s6_addr32[3]; \
|
||||||
|
ip6_addr_clear_zone(target_ip6addr);}
|
||||||
|
|
||||||
|
|
||||||
|
struct esp_ip6_addr {
|
||||||
|
uint32_t addr[4];
|
||||||
|
uint8_t zone;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct esp_ip4_addr {
|
||||||
|
uint32_t addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct esp_ip4_addr esp_ip4_addr_t;
|
||||||
|
|
||||||
|
typedef struct esp_ip6_addr esp_ip6_addr_t;
|
||||||
|
|
||||||
|
typedef struct _ip_addr {
|
||||||
|
union {
|
||||||
|
esp_ip6_addr_t ip6;
|
||||||
|
esp_ip4_addr_t ip4;
|
||||||
|
} u_addr;
|
||||||
|
uint8_t type;
|
||||||
|
} esp_ip_addr_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ESP_IP6_ADDR_IS_UNKNOWN,
|
||||||
|
ESP_IP6_ADDR_IS_GLOBAL,
|
||||||
|
ESP_IP6_ADDR_IS_LINK_LOCAL,
|
||||||
|
ESP_IP6_ADDR_IS_SITE_LOCAL,
|
||||||
|
ESP_IP6_ADDR_IS_UNIQUE_LOCAL,
|
||||||
|
ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6
|
||||||
|
} esp_ip6_addr_type_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
esp_ip4_addr_t ip; /**< Interface IPV4 address */
|
||||||
|
esp_ip4_addr_t netmask; /**< Interface IPV4 netmask */
|
||||||
|
esp_ip4_addr_t gw; /**< Interface IPV4 gateway address */
|
||||||
|
} esp_netif_ip_info_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
esp_ip6_addr_t ip; /**< Interface IPV6 address */
|
||||||
|
} esp_netif_ip6_info_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the IPv6 address type
|
||||||
|
*
|
||||||
|
* @param[in] ip6_addr IPv6 type
|
||||||
|
*
|
||||||
|
* @return IPv6 type in form of enum esp_ip6_addr_type_t
|
||||||
|
*/
|
||||||
|
esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //_ESP_NETIF_IP_ADDR_H_
|
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _ESP_NETIF_PPP_H_
|
||||||
|
#define _ESP_NETIF_PPP_H_
|
||||||
|
|
||||||
|
#define NETIF_PP_PHASE_OFFSET 0x100
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_ESP_NETIF_PPP_H_
|
@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(INCLUDE_DIRS include
|
||||||
|
REQUIRES esp_netif_linux esp_event_mock)
|
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef int uart_port_t;
|
||||||
|
typedef int uart_word_length_t;
|
||||||
|
typedef int uart_stop_bits_t;
|
||||||
|
typedef int uart_parity_t;
|
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "esp_system_common_declares.h"
|
||||||
|
|
||||||
|
typedef int esp_err_t;
|
||||||
|
|
||||||
|
#define ESP_FAIL -1
|
||||||
|
#define ESP_OK 0
|
||||||
|
|
||||||
|
#define ESP_ERR_NO_MEM 0x101
|
||||||
|
#define ESP_ERR_INVALID_ARG 0x102
|
||||||
|
#define ESP_ERR_INVALID_STATE 0x103
|
||||||
|
#define ESP_ERR_INVALID_SIZE 0x104
|
||||||
|
#define ESP_ERR_NOT_FOUND 0x105
|
||||||
|
#define ESP_ERR_NOT_SUPPORTED 0x106
|
||||||
|
#define ESP_ERR_TIMEOUT 0x107
|
||||||
|
#define ESP_ERR_INVALID_RESPONSE 0x
|
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/10/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MDNS_HOST_ESP_LOG_H
|
||||||
|
#define MDNS_HOST_ESP_LOG_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define ESP_LOG_INFO 1
|
||||||
|
#define ESP_LOG_BUFFER_HEXDUMP(...)
|
||||||
|
|
||||||
|
#define ESP_LOGE(TAG, ...)
|
||||||
|
//printf(TAG); printf("ERROR: " __VA_ARGS__); printf("\n")
|
||||||
|
#define ESP_LOGW(TAG, ...)
|
||||||
|
//printf(TAG); printf("WARN: "__VA_ARGS__); printf("\n")
|
||||||
|
#define ESP_LOGI(TAG, ...)
|
||||||
|
//printf(TAG); printf("INFO: "__VA_ARGS__); printf("\n")
|
||||||
|
#define ESP_LOGD(TAG, ...)
|
||||||
|
//printf(TAG); printf("DEBUG: "__VA_ARGS__); printf("\n")
|
||||||
|
|
||||||
|
#endif //MDNS_HOST_ESP_LOG_H
|
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/17/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MDNS_HOST_ESP_SYSTEM_COMMON_DECLARES_H
|
||||||
|
#define MDNS_HOST_ESP_SYSTEM_COMMON_DECLARES_H
|
||||||
|
|
||||||
|
struct esp_netif_obj;
|
||||||
|
|
||||||
|
typedef struct esp_netif_obj esp_netif_t;
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MDNS_HOST_ESP_SYSTEM_COMMON_DECLARES_H
|
@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 2/17/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MDNS_HOST_ENDIAN_H
|
||||||
|
#define MDNS_HOST_ENDIAN_H
|
||||||
|
|
||||||
|
#include_next "endian.h"
|
||||||
|
|
||||||
|
#endif //MDNS_HOST_ENDIAN_H
|
10
esp_modem/test/host_test/main/CMakeLists.txt
Normal file
10
esp_modem/test/host_test/main/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
idf_component_register(SRCS "test_modem.cpp"
|
||||||
|
INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch"
|
||||||
|
REQUIRES esp_modem)
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads)
|
||||||
|
|
||||||
|
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")
|
145
esp_modem/test/host_test/main/test_modem.cpp
Normal file
145
esp_modem/test/host_test/main/test_modem.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#define CATCH_CONFIG_MAIN // This tells the catch header to generate a main
|
||||||
|
#include <memory>
|
||||||
|
#include <future>
|
||||||
|
#include "catch.hpp"
|
||||||
|
#include "cxx_include/esp_modem_terminal.hpp"
|
||||||
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
|
|
||||||
|
using namespace esp_modem;
|
||||||
|
|
||||||
|
class LoopbackTerm : public Terminal {
|
||||||
|
public:
|
||||||
|
explicit LoopbackTerm(): loopback_data(), data_len(0) {}
|
||||||
|
|
||||||
|
~LoopbackTerm() override = default;
|
||||||
|
|
||||||
|
void start() override {
|
||||||
|
status = status_t::STARTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() override {
|
||||||
|
status = status_t::STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write(uint8_t *data, size_t len) override {
|
||||||
|
if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) {
|
||||||
|
std::string command((char*)data, len);
|
||||||
|
std::string response;
|
||||||
|
if (command == "ATE1\r" || command == "ATE0\r" || command == "+++") {
|
||||||
|
response = "OK\r\n";
|
||||||
|
} else if (command == "ATO\r") {
|
||||||
|
response = "ERROR\r\n";
|
||||||
|
} else if (command.find("ATD") != std::string::npos) {
|
||||||
|
response = "CONNECT\r\n";
|
||||||
|
} else if (command.find("AT") != std::string::npos) {
|
||||||
|
response = "OK\r\n";
|
||||||
|
}
|
||||||
|
if (!response.empty()) {
|
||||||
|
data_len = response.length();
|
||||||
|
loopback_data.resize(data_len);
|
||||||
|
memcpy(&loopback_data[0], &response[0], data_len);
|
||||||
|
auto ret = std::async(on_data, data_len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loopback_data.resize(data_len + len);
|
||||||
|
memcpy(&loopback_data[data_len], data, len);
|
||||||
|
data_len += len;
|
||||||
|
auto ret = std::async(on_data, data_len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read(uint8_t *data, size_t len) override {
|
||||||
|
size_t read_len = std::min(data_len, len);
|
||||||
|
if (read_len) {
|
||||||
|
memcpy(data, &loopback_data[0], len);
|
||||||
|
loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len);
|
||||||
|
data_len -= len;
|
||||||
|
}
|
||||||
|
return read_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_data_cb(std::function<bool(size_t len)> f) override {
|
||||||
|
on_data = std::move(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class status_t {
|
||||||
|
STARTED,
|
||||||
|
STOPPED
|
||||||
|
};
|
||||||
|
status_t status;
|
||||||
|
signal_group signal;
|
||||||
|
std::vector<uint8_t> loopback_data;
|
||||||
|
size_t data_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("DTE send/receive command", "[esp_modem]")
|
||||||
|
{
|
||||||
|
auto term = std::make_unique<LoopbackTerm>();
|
||||||
|
auto dte = std::make_unique<DTE>(std::move(term));
|
||||||
|
|
||||||
|
const auto test_command = "Test\n";
|
||||||
|
CHECK(term == nullptr);
|
||||||
|
|
||||||
|
dte->set_mode(esp_modem::modem_mode::COMMAND_MODE);
|
||||||
|
|
||||||
|
auto ret = dte->command(test_command, [&](uint8_t *data, size_t len) {
|
||||||
|
std::string response((char*)data, len);
|
||||||
|
CHECK(response == test_command);
|
||||||
|
return command_result::OK;
|
||||||
|
}, 1000);
|
||||||
|
CHECK(ret == command_result::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DCE commands", "[esp_modem]")
|
||||||
|
{
|
||||||
|
auto term = std::make_unique<LoopbackTerm>();
|
||||||
|
auto dte = std::make_shared<DTE>(std::move(term));
|
||||||
|
CHECK(term == nullptr);
|
||||||
|
|
||||||
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
|
||||||
|
esp_netif_t netif{};
|
||||||
|
auto dce = create_SIM7600_dce(&dce_config, dte, &netif);
|
||||||
|
CHECK(dce != nullptr);
|
||||||
|
|
||||||
|
const auto test_command = "Test\n";
|
||||||
|
auto ret = dce->command(test_command, [&](uint8_t *data, size_t len) {
|
||||||
|
std::string response((char*)data, len);
|
||||||
|
CHECK(response == test_command);
|
||||||
|
return command_result::OK;
|
||||||
|
}, 1000);
|
||||||
|
CHECK(ret == command_result::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DCE AT commands", "[esp_modem]")
|
||||||
|
{
|
||||||
|
auto term = std::make_unique<LoopbackTerm>();
|
||||||
|
auto dte = std::make_shared<DTE>(std::move(term));
|
||||||
|
CHECK(term == nullptr);
|
||||||
|
|
||||||
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
|
||||||
|
esp_netif_t netif{};
|
||||||
|
auto dce = create_SIM7600_dce(&dce_config, dte, &netif);
|
||||||
|
CHECK(dce != nullptr);
|
||||||
|
|
||||||
|
CHECK(dce->set_echo(false) == command_result::OK);
|
||||||
|
CHECK(dce->set_echo(true) == command_result::OK);
|
||||||
|
CHECK(dce->resume_data_mode() == command_result::FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DCE modes", "[esp_modem]")
|
||||||
|
{
|
||||||
|
auto term = std::make_unique<LoopbackTerm>();
|
||||||
|
auto dte = std::make_shared<DTE>(std::move(term));
|
||||||
|
CHECK(term == nullptr);
|
||||||
|
|
||||||
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
|
||||||
|
esp_netif_t netif{};
|
||||||
|
auto dce = create_SIM7600_dce(&dce_config, dte, &netif);
|
||||||
|
CHECK(dce != nullptr);
|
||||||
|
|
||||||
|
CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == false);
|
||||||
|
CHECK(dce->set_mode(esp_modem::modem_mode::DATA_MODE) == true);
|
||||||
|
CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true);
|
||||||
|
}
|
5
esp_modem/test/host_test/sdkconfig.defaults
Normal file
5
esp_modem/test/host_test/sdkconfig.defaults
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CONFIG_IDF_TARGET="linux"
|
||||||
|
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||||
|
CONFIG_COMPILER_CXX_RTTI=y
|
||||||
|
CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
|
||||||
|
CONFIG_COMPILER_STACK_CHECK_NONE=y
|
8
esp_modem/test/target/CMakeLists.txt
Normal file
8
esp_modem/test/target/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# The following five lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
set(EXTRA_COMPONENT_DIRS "../..")
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(pppd_test)
|
6
esp_modem/test/target/main/CMakeLists.txt
Normal file
6
esp_modem/test/target/main/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
idf_component_register(SRCS "pppd_test.cpp"
|
||||||
|
"NetworkDCE.cpp"
|
||||||
|
INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch"
|
||||||
|
REQUIRES esp_modem)
|
||||||
|
|
||||||
|
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
26
esp_modem/test/target/main/Kconfig.projbuild
Normal file
26
esp_modem/test/target/main/Kconfig.projbuild
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
menu "Example Configuration"
|
||||||
|
|
||||||
|
config ESP_WIFI_SSID
|
||||||
|
string "WiFi SSID"
|
||||||
|
default "myssid"
|
||||||
|
help
|
||||||
|
SSID (network name) for the example to connect to.
|
||||||
|
|
||||||
|
config ESP_WIFI_PASSWORD
|
||||||
|
string "WiFi Password"
|
||||||
|
default "mypassword"
|
||||||
|
help
|
||||||
|
WiFi password (WPA or WPA2) for the example to use.
|
||||||
|
config ESP_WIFI_CHANNEL
|
||||||
|
int "WiFi Channel"
|
||||||
|
range 1 13
|
||||||
|
default 1
|
||||||
|
help
|
||||||
|
WiFi channel (network channel) for the example to use.
|
||||||
|
|
||||||
|
config ESP_MAX_STA_CONN
|
||||||
|
int "Maximal STA connections"
|
||||||
|
default 4
|
||||||
|
help
|
||||||
|
Max number of the STA connects to AP.
|
||||||
|
endmenu
|
78
esp_modem/test/target/main/NetworkDCE.cpp
Normal file
78
esp_modem/test/target/main/NetworkDCE.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 3/25/21.
|
||||||
|
//
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
|
#include "esp_modem_config.h"
|
||||||
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
|
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace esp_modem;
|
||||||
|
using namespace esp_modem::dce_factory;
|
||||||
|
|
||||||
|
class NetModule;
|
||||||
|
typedef DCE_T<NetModule> NetDCE;
|
||||||
|
|
||||||
|
class NetDCE_Factory: public Factory {
|
||||||
|
public:
|
||||||
|
template <typename T, typename ...Args>
|
||||||
|
static DCE_T<T>* create(const config *cfg, Args&&... args)
|
||||||
|
{
|
||||||
|
return build_generic_DCE< /* Object to create */ DCE_T<T>, /* vanilla pointer */ DCE_T<T> *, /* module */ T>
|
||||||
|
(cfg, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetModule: public ModuleIf {
|
||||||
|
public:
|
||||||
|
explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg):
|
||||||
|
dte(std::move(dte)) {}
|
||||||
|
|
||||||
|
bool setup_data_mode() override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool set_mode(modem_mode mode) override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t init(esp_netif_t *netif)
|
||||||
|
{
|
||||||
|
// configure
|
||||||
|
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||||
|
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("");
|
||||||
|
|
||||||
|
// create DTE and minimal network DCE
|
||||||
|
auto uart_dte = create_uart_dte(&dte_config);
|
||||||
|
dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif);
|
||||||
|
return dce == nullptr ? ESP_FAIL : ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deinit() { delete dce; }
|
||||||
|
static void start() { dce->set_data(); }
|
||||||
|
static void stop() { dce->exit_data(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static NetDCE *dce;
|
||||||
|
std::shared_ptr<DTE> dte;
|
||||||
|
};
|
||||||
|
|
||||||
|
NetDCE *NetModule::dce = nullptr;
|
||||||
|
|
||||||
|
esp_err_t modem_init_network(esp_netif_t *netif)
|
||||||
|
{
|
||||||
|
return NetModule::init(netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void modem_start_network()
|
||||||
|
{
|
||||||
|
NetModule::start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void modem_stop_network()
|
||||||
|
{
|
||||||
|
NetModule::stop();
|
||||||
|
}
|
125
esp_modem/test/target/main/pppd_test.cpp
Normal file
125
esp_modem/test/target/main/pppd_test.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_ppp.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
static const char *TAG = "pppd_test";
|
||||||
|
static EventGroupHandle_t event_group = NULL;
|
||||||
|
|
||||||
|
static void on_modem_event(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
if (event_base == IP_EVENT) {
|
||||||
|
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||||
|
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||||
|
esp_netif_dns_info_t dns_info;
|
||||||
|
|
||||||
|
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
|
esp_netif_t *netif = event->esp_netif;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
|
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
|
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||||
|
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||||
|
esp_netif_get_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns_info);
|
||||||
|
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||||
|
esp_netif_get_dns_info(netif, ESP_NETIF_DNS_BACKUP, &dns_info);
|
||||||
|
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||||
|
xEventGroupSetBits(event_group, 1);
|
||||||
|
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||||
|
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||||
|
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||||
|
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||||
|
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||||
|
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "PPP state changed event %d", event_id);
|
||||||
|
if (event_id == NETIF_PPP_ERRORUSER) {
|
||||||
|
/* User interrupted event from esp-netif */
|
||||||
|
esp_netif_t *netif = static_cast<esp_netif_t *>(event_data);
|
||||||
|
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
||||||
|
xEventGroupSetBits(event_group, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t modem_init_network(esp_netif_t *netif);
|
||||||
|
void modem_start_network();
|
||||||
|
void modem_stop_network();
|
||||||
|
|
||||||
|
extern "C" void app_main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
event_group = xEventGroupCreate();
|
||||||
|
|
||||||
|
// init the DTE
|
||||||
|
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
|
esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config);
|
||||||
|
assert(ppp_netif);
|
||||||
|
esp_netif_ppp_config_t ppp_config = { true, true };
|
||||||
|
esp_netif_ppp_set_params(ppp_netif, &ppp_config);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(modem_init_network(ppp_netif));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_modem_event, nullptr));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, nullptr));
|
||||||
|
|
||||||
|
modem_start_network();
|
||||||
|
Catch::Session session;
|
||||||
|
int numFailed = session.run();
|
||||||
|
if (numFailed > 0) {
|
||||||
|
ESP_LOGE(TAG, "Test FAILED!");
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "Test passed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Connect test", "[esp_modem]")
|
||||||
|
{
|
||||||
|
EventBits_t b = xEventGroupWaitBits(event_group, 1, pdTRUE, pdFALSE, pdMS_TO_TICKS(15000));
|
||||||
|
CHECK(b == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Disconnection test", "[esp_modem]")
|
||||||
|
{
|
||||||
|
modem_stop_network();
|
||||||
|
EventBits_t b = xEventGroupWaitBits(event_group, 2, pdTRUE, pdFALSE, pdMS_TO_TICKS(15000));
|
||||||
|
CHECK(b == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
static void handle(int nr)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Signal handler %d", nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_sig_func_ptr signal (int nr, _sig_func_ptr)
|
||||||
|
{
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user