mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-19 05:22:21 +02:00
CMUX: Initial version of CMUX implementation
This commit is contained in:
@ -61,7 +61,7 @@ is provided implementing these method using the uart driver.
|
||||
|
||||
## CMUX terminal
|
||||
|
||||
The below diagram depicts the idea of using CMUX terminal mode using the CMUXedTerminal class which is a terminal
|
||||
The below diagram depicts the idea of using CMUX terminal mode using the CMux class which is a terminal
|
||||
(it implements the basic read/write methods) interfacing arbitrary number of virtual terminals,
|
||||
but at the same time it is also composed of another terminal, the real terminal, which is multiplexed.
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
static const char *TAG = "pppos_example";
|
||||
static EventGroupHandle_t event_group = NULL;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
@ -114,7 +116,6 @@ static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||
}
|
||||
|
||||
|
||||
static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_config_t *dce_config, esp_netif_config_t *ppp_config);
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
@ -167,7 +168,7 @@ extern "C" void app_main(void)
|
||||
|
||||
std::string apn = "internet";
|
||||
// auto device = create_generic_module(uart_dte, apn);
|
||||
auto device = create_SIM7600_module(uart_dte, apn);
|
||||
// auto device = create_SIM7600_module(uart_dte, apn);
|
||||
// bool pin_ok = true;
|
||||
// if (device->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
||||
// throw_if_false(device->set_pin("1234") == command_result::OK, "Cannot set PIN!");
|
||||
@ -187,37 +188,45 @@ extern "C" void app_main(void)
|
||||
// std::cout << "|" << number << "|" << std::endl;
|
||||
// std::cout << "----" << std::endl;
|
||||
// auto my_dce = create_generic_module_dce(uart_dte, device, esp_netif);
|
||||
auto my_dce = create_SIM7600_dce_from_module(uart_dte, device, esp_netif);
|
||||
auto my_dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
|
||||
my_dce->set_command_mode();
|
||||
my_dce->get_module_name(number);
|
||||
std::cout << "|" << number << "|" << std::endl;
|
||||
bool pin_ok = true;
|
||||
if (my_dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
||||
throw_if_false(my_dce->set_pin("1234") == command_result::OK, "Cannot set PIN!");
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
// return;
|
||||
// my_dce->set_cmux();
|
||||
// my_dce->set_cmux();
|
||||
my_dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
|
||||
my_dce->get_imsi(number);
|
||||
std::cout << "|" << number << "|" << std::endl;
|
||||
|
||||
// while (1) {
|
||||
// vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
// uart_dte->write((uint8_t*)"AT+CPIN?\r", 9);
|
||||
// my_dce->get_imsi(number);
|
||||
// std::cout << "|" << number << "|" << std::endl;
|
||||
//
|
||||
// }
|
||||
// uart_dte->send_cmux_command(2, "AT+CPIN?");
|
||||
// return;
|
||||
|
||||
my_dce->get_module_name(number);
|
||||
my_dce->set_data_mode();
|
||||
// my_dce->get_module_name(number);
|
||||
// my_dce->set_data_mode();
|
||||
//
|
||||
// my_dce->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
|
||||
// std::string response((char*)data, len);
|
||||
// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data);
|
||||
// std::cout << response << std::endl;
|
||||
// return command_result::OK;
|
||||
// }, 1000);
|
||||
|
||||
my_dce->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
|
||||
std::string response((char*)data, len);
|
||||
ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data);
|
||||
std::cout << response << std::endl;
|
||||
return command_result::OK;
|
||||
}, 1000);
|
||||
|
||||
while (1) {
|
||||
|
||||
// while (1)
|
||||
{
|
||||
|
||||
my_dce->set_data();
|
||||
/* Config MQTT */
|
||||
@ -230,14 +239,20 @@ extern "C" void app_main(void)
|
||||
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
esp_mqtt_client_destroy(mqtt_client);
|
||||
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
my_dce->get_imsi(number);
|
||||
std::cout << "|" << number << "|" << std::endl;
|
||||
}
|
||||
|
||||
// vTaskDelay(pdMS_TO_TICKS(20000));
|
||||
my_dce->exit_data();
|
||||
uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
|
||||
std::string response((char*)data, len);
|
||||
// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data);
|
||||
std::cout << response << std::endl;
|
||||
return command_result::OK;
|
||||
}, 1000);
|
||||
// my_dce->exit_data();
|
||||
// uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
|
||||
// std::string response((char*)data, len);
|
||||
//// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data);
|
||||
// std::cout << response << std::endl;
|
||||
// return command_result::OK;
|
||||
// }, 1000);
|
||||
}
|
||||
|
||||
// ddd->send_command("AT+COPS=?\r", [&](uint8_t *data, size_t len) {
|
||||
|
@ -15,7 +15,11 @@
|
||||
#ifndef _ESP_MODEM_CMUX_HPP_
|
||||
#define _ESP_MODEM_CMUX_HPP_
|
||||
|
||||
#include "esp_modem_terminal.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
constexpr size_t max_terms = 2;
|
||||
/**
|
||||
* @defgroup ESP_MODEM_CMUX ESP_MODEM CMUX class
|
||||
* @brief Definition of CMUX terminal
|
||||
@ -43,19 +47,20 @@ enum class cmux_state {
|
||||
*
|
||||
* @note Implementation of CMUX protocol is experimental
|
||||
*/
|
||||
class CMUXedTerminal: public Terminal {
|
||||
class CMuxInstance;
|
||||
|
||||
class CMux {
|
||||
public:
|
||||
explicit CMUXedTerminal(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size):
|
||||
term(std::move(t)), buffer(std::move(b)) {}
|
||||
~CMUXedTerminal() override = default;
|
||||
void setup_cmux();
|
||||
void set_data_cb(std::function<bool(size_t len)> f) override {}
|
||||
int write(uint8_t *data, size_t len) override;
|
||||
int read(uint8_t *data, size_t len) override { return term->read(data, len); }
|
||||
void start() override;
|
||||
void stop() override {}
|
||||
explicit CMux(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size):
|
||||
term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)) {}
|
||||
~CMux() = default;
|
||||
void init();
|
||||
void set_read_cb(int inst, std::function<bool(uint8_t *data, size_t len)> f);
|
||||
|
||||
int write(int i, uint8_t *data, size_t len);
|
||||
private:
|
||||
static bool process_cmux_recv(size_t len);
|
||||
std::function<bool(uint8_t *data, size_t len)> read_cb[max_terms];
|
||||
void data_available(uint8_t *data, size_t len);
|
||||
void send_sabm(size_t i);
|
||||
std::unique_ptr<Terminal> term;
|
||||
cmux_state state;
|
||||
@ -65,9 +70,25 @@ private:
|
||||
uint8_t frame_header[6];
|
||||
size_t frame_header_offset;
|
||||
size_t buffer_size;
|
||||
size_t consumed;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
bool on_cmux(size_t len);
|
||||
bool on_cmux(uint8_t *data, size_t len);
|
||||
static uint8_t fcs_crc(const uint8_t frame[6]);
|
||||
Lock lock;
|
||||
int instance;
|
||||
};
|
||||
|
||||
class CMuxInstance: public Terminal {
|
||||
public:
|
||||
explicit CMuxInstance(std::shared_ptr<CMux> parent, int i): cmux(std::move(parent)), instance(i) {}
|
||||
|
||||
int write(uint8_t *data, size_t len) override { return cmux->write(instance, data, len); }
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override { return cmux->set_read_cb(instance, std::move(f)); }
|
||||
int read(uint8_t *data, size_t len) override { return 0; }
|
||||
void start() override { }
|
||||
void stop() override { }
|
||||
private:
|
||||
std::shared_ptr<CMux> cmux;
|
||||
int instance;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -42,8 +42,17 @@ public:
|
||||
return actual_len;
|
||||
}
|
||||
|
||||
void set_data_cb(std::function<bool(size_t len)> f) {
|
||||
term->set_data_cb(std::move(f));
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f)
|
||||
{
|
||||
on_data = std::move(f);
|
||||
term->set_read_cb([this](uint8_t *data, size_t len) {
|
||||
if (!data) {
|
||||
auto data_to_read = std::min(len, buffer_size - consumed);
|
||||
data = buffer.get();
|
||||
len = term->read(data, data_to_read);
|
||||
}
|
||||
return on_data(data, len);
|
||||
});
|
||||
}
|
||||
|
||||
void start() { term->start(); }
|
||||
@ -54,7 +63,10 @@ public:
|
||||
term->start();
|
||||
mode = m;
|
||||
if (m == modem_mode::DATA_MODE) {
|
||||
term->set_data_cb(on_data);
|
||||
term->set_read_cb(on_data);
|
||||
if (other_term) { // if we have the other terminal, let's use it for commands
|
||||
command_term = other_term.get();
|
||||
}
|
||||
} else if (m == modem_mode::CMUX_MODE) {
|
||||
setup_cmux();
|
||||
}
|
||||
@ -62,23 +74,32 @@ public:
|
||||
|
||||
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) override;
|
||||
|
||||
void send_cmux_command(uint8_t i, const std::string &command);
|
||||
|
||||
private:
|
||||
Lock lock;
|
||||
|
||||
void setup_cmux();
|
||||
// command_result command(Terminal *t, const std::string &command, got_line_cb got_line, uint32_t time_ms);
|
||||
|
||||
static const size_t GOT_LINE = signal_group::bit0;
|
||||
size_t buffer_size;
|
||||
size_t consumed;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
std::unique_ptr<Terminal> term;
|
||||
Terminal *command_term;
|
||||
std::unique_ptr<Terminal> other_term;
|
||||
modem_mode mode;
|
||||
signal_group signal;
|
||||
std::function<bool(size_t len)> on_data;
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data;
|
||||
};
|
||||
|
||||
//class DTE_inst: public DTE {
|
||||
//public:
|
||||
// DTE_inst(std::shared_ptr<DTE> parent) : DTE(t), dte(parent) {}
|
||||
//private:
|
||||
// std::shared_ptr<DTE> dte;
|
||||
//};
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DTE_HPP_
|
||||
|
@ -36,9 +36,10 @@ class Terminal {
|
||||
public:
|
||||
virtual ~Terminal() = default;
|
||||
|
||||
virtual void set_data_cb(std::function<bool(size_t len)> f) { on_data = std::move(f); }
|
||||
// virtual void set_data_cb(std::function<bool(size_t len)> f) { on_data = std::move(f); }
|
||||
|
||||
void set_error_cb(std::function<void(terminal_error)> f) { on_error = std::move(f); }
|
||||
virtual void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) { on_data = std::move(f); }
|
||||
|
||||
virtual int write(uint8_t *data, size_t len) = 0;
|
||||
|
||||
@ -51,7 +52,8 @@ public:
|
||||
virtual size_t max_virtual_terms() { return 1; }
|
||||
|
||||
protected:
|
||||
std::function<bool(size_t len)> on_data;
|
||||
// std::function<bool(size_t len)> on_data;
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data;
|
||||
std::function<void(terminal_error)> on_error;
|
||||
};
|
||||
|
||||
|
@ -14,16 +14,13 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <cxx_include/esp_modem_cmux.hpp>
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_log.h"
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
/* CRC8 is the reflected CRC8/ROHC algorithm */
|
||||
#define FCS_POLYNOMIAL 0xe0 /* reversed crc8 */
|
||||
#define FCS_INIT_VALUE 0xFF
|
||||
#define FCS_GOOD_VALUE 0xCF
|
||||
|
||||
#define EA 0x01 /* Extension bit */
|
||||
#define CR 0x02 /* Command / Response */
|
||||
#define PF 0x10 /* Poll / Final */
|
||||
@ -54,86 +51,59 @@ using namespace esp_modem;
|
||||
|
||||
/* Flag sequence field between messages (start of frame) */
|
||||
#define SOF_MARKER 0xF9
|
||||
static uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
|
||||
bool reversed)
|
||||
|
||||
uint8_t CMux::fcs_crc(const uint8_t frame[6])
|
||||
{
|
||||
uint8_t crc = initial_value;
|
||||
size_t i, j;
|
||||
// #define FCS_GOOD_VALUE 0xCF
|
||||
uint8_t crc = 0xFF; // FCS_INIT_VALUE
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= src[i];
|
||||
for (int i = 1; i < 4; i++) {
|
||||
crc ^= frame[i];
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (reversed) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (crc & 0x01) {
|
||||
crc = (crc >> 1) ^ polynomial;
|
||||
crc = (crc >> 1) ^ 0xe0; // FCS_POLYNOMIAL
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
} else {
|
||||
if (crc & 0x80) {
|
||||
crc = (crc << 1) ^ polynomial;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
void CMUXedTerminal::start()
|
||||
{
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
send_sabm(i);
|
||||
usleep(100'000);
|
||||
}
|
||||
}
|
||||
|
||||
void CMUXedTerminal::send_sabm(size_t dlci)
|
||||
void CMux::send_sabm(size_t dlci)
|
||||
{
|
||||
uint8_t frame[6];
|
||||
frame[0] = SOF_MARKER;
|
||||
frame[1] = (dlci << 2) | 0x3;
|
||||
frame[2] = FT_SABM | PF;
|
||||
frame[3] = 1;
|
||||
frame[4] = 0xFF - crc8(&frame[1], 3, FCS_POLYNOMIAL, FCS_INIT_VALUE, true);
|
||||
frame[4] = 0xFF - fcs_crc(frame);
|
||||
frame[5] = SOF_MARKER;
|
||||
term->write(frame, 6);
|
||||
}
|
||||
|
||||
bool CMUXedTerminal::process_cmux_recv(size_t len)
|
||||
|
||||
void CMux::data_available(uint8_t *data, size_t len)
|
||||
{
|
||||
return false;
|
||||
if (type == 0xFF && len > 0 && dlci > 0) {
|
||||
int virtual_term = dlci - 1;
|
||||
if (virtual_term < max_terms && read_cb[virtual_term])
|
||||
read_cb[virtual_term](data, len);
|
||||
}
|
||||
}
|
||||
|
||||
bool output(uint8_t *data, size_t len, std::string message)
|
||||
bool CMux::on_cmux(uint8_t *data, size_t actual_len)
|
||||
{
|
||||
// printf("OUTPUT: %s len=%ld \n", message.c_str(), len);
|
||||
for (int i=0; i< len; ++i) {
|
||||
printf("0x%02x, ",data[i]);
|
||||
if (!data) {
|
||||
auto data_to_read = std::min(actual_len, buffer_size);
|
||||
data = buffer.get();
|
||||
actual_len = term->read(data, data_to_read);
|
||||
}
|
||||
printf("----\n");
|
||||
|
||||
printf("%.*s", (int)len, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMUXedTerminal::on_cmux(size_t len)
|
||||
{
|
||||
auto data_to_read = std::min(len, buffer_size);
|
||||
auto data = buffer.get();
|
||||
auto actual_len = term->read(data, data_to_read);
|
||||
// consumed += actual_len;
|
||||
ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_INFO);
|
||||
for (int i=0; i< len; ++i) {
|
||||
printf("0x%02x, ",data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_VERBOSE);
|
||||
uint8_t* frame = data;
|
||||
auto available_len = len;
|
||||
auto available_len = actual_len;
|
||||
size_t payload_offset = 0;
|
||||
size_t footer_offset = 0;
|
||||
while (available_len > 0) {
|
||||
@ -171,12 +141,12 @@ bool CMUXedTerminal::on_cmux(size_t len)
|
||||
case cmux_state::PAYLOAD:
|
||||
if (available_len < payload_len) { // payload
|
||||
state = cmux_state::PAYLOAD;
|
||||
output(frame, available_len, "PAYLOAD partial read"); // partial read
|
||||
data_available(frame, available_len); // partial read
|
||||
payload_len -= available_len;
|
||||
return false;
|
||||
} else { // complete
|
||||
if (payload_len > 0) {
|
||||
output(&frame[0], payload_len, "PAYLOAD full read"); // rest read
|
||||
data_available(&frame[0], payload_len); // rest read
|
||||
}
|
||||
available_len -= payload_len;
|
||||
frame += payload_len;
|
||||
@ -196,7 +166,7 @@ bool CMUXedTerminal::on_cmux(size_t len)
|
||||
return true;
|
||||
}
|
||||
if (payload_len == 0) {
|
||||
output(frame_header, 0, "Null payload");
|
||||
data_available(frame_header, 0); // Null payload
|
||||
}
|
||||
frame += footer_offset;
|
||||
available_len -= footer_offset;
|
||||
@ -208,12 +178,12 @@ bool CMUXedTerminal::on_cmux(size_t len)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void CMUXedTerminal::setup_cmux()
|
||||
void CMux::init()
|
||||
{
|
||||
frame_header_offset = 0;
|
||||
state = cmux_state::INIT;
|
||||
term->set_data_cb([this](size_t len){
|
||||
this->on_cmux(len);
|
||||
term->set_read_cb([this](uint8_t *data, size_t len) {
|
||||
this->on_cmux(data, len);
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -224,51 +194,27 @@ void CMUXedTerminal::setup_cmux()
|
||||
}
|
||||
}
|
||||
|
||||
void DTE::setup_cmux()
|
||||
{
|
||||
auto original_term = std::move(term);
|
||||
auto cmux_term = std::make_unique<CMUXedTerminal>(std::move(original_term), std::move(buffer), buffer_size);
|
||||
buffer_size = 0;
|
||||
cmux_term->setup_cmux();
|
||||
term = std::move(cmux_term);
|
||||
}
|
||||
int CMux::write(int virtual_term, uint8_t *data, size_t len) {
|
||||
|
||||
|
||||
void DTE::send_cmux_command(uint8_t i, const std::string& command)
|
||||
{
|
||||
|
||||
uint8_t frame[6];
|
||||
frame[0] = SOF_MARKER;
|
||||
frame[1] = (i << 2) + 1;
|
||||
frame[2] = FT_UIH;
|
||||
frame[3] = (command.length() << 1) + 1;
|
||||
frame[4] = 0xFF - crc8(&frame[1], 3, FCS_POLYNOMIAL, FCS_INIT_VALUE, true);
|
||||
frame[5] = SOF_MARKER;
|
||||
|
||||
term->write(frame, 4);
|
||||
term->write((uint8_t *)command.c_str(), command.length());
|
||||
term->write(frame + 4, 2);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_INFO);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", (uint8_t *)command.c_str(), command.length(), ESP_LOG_INFO);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_INFO);
|
||||
}
|
||||
|
||||
int CMUXedTerminal::write(uint8_t *data, size_t len) {
|
||||
|
||||
size_t i = 1;
|
||||
int i = virtual_term + 1;
|
||||
uint8_t frame[6];
|
||||
frame[0] = SOF_MARKER;
|
||||
frame[1] = (i << 2) + 1;
|
||||
frame[2] = FT_UIH;
|
||||
frame[3] = (len << 1) + 1;
|
||||
frame[4] = 0xFF - crc8(&frame[1], 3, FCS_POLYNOMIAL, FCS_INIT_VALUE, true);
|
||||
frame[4] = 0xFF - fcs_crc(frame);
|
||||
frame[5] = SOF_MARKER;
|
||||
|
||||
term->write(frame, 4);
|
||||
term->write(data, len);
|
||||
term->write(frame + 4, 2);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_INFO);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", data, len, ESP_LOG_INFO);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_INFO);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_VERBOSE);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", data, len, ESP_LOG_VERBOSE);
|
||||
ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_VERBOSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMux::set_read_cb(int inst, std::function<bool(uint8_t *, size_t)> f) {
|
||||
if (inst < max_terms)
|
||||
read_cb[inst] = std::move(f);
|
||||
}
|
||||
|
@ -29,14 +29,12 @@ bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m)
|
||||
return false;
|
||||
netif.stop();
|
||||
device->set_mode(modem_mode::COMMAND_MODE);
|
||||
uint8_t* data;
|
||||
dte->set_data_cb([&](size_t len) -> bool {
|
||||
auto actual_len = dte->read(&data, 64);
|
||||
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, actual_len, ESP_LOG_INFO);
|
||||
dte->set_read_cb([&](uint8_t *data, size_t len) -> bool {
|
||||
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, len, ESP_LOG_INFO);
|
||||
return false;
|
||||
});
|
||||
netif.wait_until_ppp_exits();
|
||||
dte->set_data_cb(nullptr);
|
||||
dte->set_read_cb(nullptr);
|
||||
dte->set_mode(modem_mode::COMMAND_MODE);
|
||||
mode = m;
|
||||
return true;
|
||||
@ -54,6 +52,10 @@ bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m)
|
||||
return false;
|
||||
device->set_mode(modem_mode::CMUX_MODE);
|
||||
dte->set_mode(modem_mode::CMUX_MODE);
|
||||
// auto dte1 = create_virtual(dte, 1);
|
||||
// auto dte2 = create_virtual(dte, 2);
|
||||
// device->swap_dte(dte1);
|
||||
// netif->swap_dte(dte2;);
|
||||
mode = modem_mode::COMMAND_MODE;
|
||||
return true;
|
||||
}
|
||||
|
@ -23,19 +23,22 @@ const int DTE_BUFFER_SIZE = 1024;
|
||||
DTE::DTE(std::unique_ptr<Terminal> terminal):
|
||||
buffer_size(DTE_BUFFER_SIZE), consumed(0),
|
||||
buffer(std::make_unique<uint8_t[]>(buffer_size)),
|
||||
term(std::move(terminal)), mode(modem_mode::UNDEF) {}
|
||||
term(std::move(terminal)), command_term(term.get()), other_term(nullptr),
|
||||
mode(modem_mode::UNDEF) {}
|
||||
|
||||
command_result DTE::command(const std::string &command, got_line_cb got_line, uint32_t time_ms)
|
||||
{
|
||||
Scoped<Lock> l(lock);
|
||||
command_result res = command_result::TIMEOUT;
|
||||
term->set_data_cb([&](size_t len){
|
||||
command_term->set_read_cb([&](uint8_t *data, size_t len) {
|
||||
if (!data) {
|
||||
auto data_to_read = std::min(len, buffer_size - consumed);
|
||||
auto data = buffer.get() + consumed;
|
||||
auto actual_len = term->read(data, data_to_read);
|
||||
consumed += actual_len;
|
||||
if (memchr(data, '\n', actual_len)) {
|
||||
res = got_line(buffer.get(), consumed);
|
||||
data = buffer.get() + consumed;
|
||||
len = command_term->read(data, data_to_read);
|
||||
}
|
||||
consumed += len;
|
||||
if (memchr(data, '\n', len)) {
|
||||
res = got_line(data, consumed);
|
||||
if (res == command_result::OK || res == command_result::FAIL) {
|
||||
signal.set(GOT_LINE);
|
||||
return true;
|
||||
@ -43,12 +46,23 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
|
||||
}
|
||||
return false;
|
||||
});
|
||||
term->write((uint8_t *)command.c_str(), command.length());
|
||||
command_term->write((uint8_t *)command.c_str(), command.length());
|
||||
auto got_lf = signal.wait(GOT_LINE, time_ms);
|
||||
if (got_lf && res == command_result::TIMEOUT) {
|
||||
throw_if_esp_fail(ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
consumed = 0;
|
||||
term->set_data_cb(nullptr);
|
||||
command_term->set_read_cb(nullptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
void DTE::setup_cmux()
|
||||
{
|
||||
auto original_term = std::move(term);
|
||||
auto cmux_term = std::make_shared<CMux>(std::move(original_term), std::move(buffer), buffer_size);
|
||||
buffer_size = 0;
|
||||
cmux_term->init();
|
||||
term = std::make_unique<CMuxInstance>(cmux_term, 0);
|
||||
command_term = term.get(); // use command terminal as previously
|
||||
other_term = std::make_unique<CMuxInstance>(cmux_term, 1);
|
||||
}
|
@ -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
|
||||
// to notify the modem layer when switching modes
|
||||
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) {
|
||||
ppp_config.ppp_error_event_enabled = true;
|
||||
esp_netif_ppp_set_params(esp_netif, &ppp_config);
|
||||
@ -81,10 +81,8 @@ Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) :
|
||||
}
|
||||
|
||||
void Netif::start() {
|
||||
ppp_dte->set_data_cb([this](size_t len) -> bool {
|
||||
uint8_t *data;
|
||||
auto actual_len = ppp_dte->read(&data, len);
|
||||
receive(data, actual_len);
|
||||
ppp_dte->set_read_cb([this](uint8_t *data, size_t len) -> bool {
|
||||
receive(data, len);
|
||||
return false;
|
||||
});
|
||||
esp_netif_action_start(driver.base.netif, nullptr, 0, nullptr);
|
||||
|
@ -149,7 +149,7 @@ public:
|
||||
|
||||
int read(uint8_t *data, size_t len) override;
|
||||
|
||||
void set_data_cb(std::function<bool(size_t len)> f) override {
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override {
|
||||
on_data = std::move(f);
|
||||
signal.set(TASK_PARAMS);
|
||||
}
|
||||
@ -185,7 +185,7 @@ std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *confi
|
||||
}
|
||||
|
||||
void uart_terminal::task() {
|
||||
std::function<bool(size_t len)> on_data_priv = nullptr;
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data_priv = nullptr;
|
||||
uart_event_t event;
|
||||
size_t len;
|
||||
signal.set(TASK_INIT);
|
||||
@ -207,7 +207,7 @@ void uart_terminal::task() {
|
||||
uart_get_buffered_data_len(uart.port, &len);
|
||||
// ESP_LOGI(TAG, "UART_DATA len=%d, on_data=%d", len, (bool)on_data);
|
||||
if (len && on_data_priv) {
|
||||
if (on_data_priv(len)) {
|
||||
if (on_data_priv(nullptr, len)) {
|
||||
on_data_priv = nullptr;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user