CMUX: Fix batch write, add recovery

This commit is contained in:
David Cermak
2021-04-15 14:59:30 +02:00
parent d47cb69b20
commit 6065d89e18
13 changed files with 275 additions and 190 deletions

View File

@ -2,6 +2,9 @@
- :cpp:func:`esp_modem::DCE::set_pin`
- :cpp:func:`esp_modem::DCE::read_pin`
- :cpp:func:`esp_modem::DCE::set_echo`
- :cpp:func:`esp_modem::DCE::sms_txt_mode`
- :cpp:func:`esp_modem::DCE::sms_character_set`
- :cpp:func:`esp_modem::DCE::send_sms`
- :cpp:func:`esp_modem::DCE::resume_data_mode`
- :cpp:func:`esp_modem::DCE::set_pdp_context`
- :cpp:func:`esp_modem::DCE::set_command_mode`

View File

@ -1,51 +1,65 @@
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
// call parametrs by names for documentation
// --- DCE command documentation starts here ---
/**
* @brief Sends the supplied PIN code
*
* @param pin Pin
*
*/ command_result esp_modem_set_pin (const char* pin); /**
* @brief Sets the supplied PIN code
* @param[in] pin Pin
* @return OK, FAIL or TIMEOUT
*/command_result esp_modem_set_pin (const char* pin); /**
* @brief Checks if the SIM needs a PIN
*
* @param[out] pin_ok Pin
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_read_pin (bool* pin_ok); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result esp_modem_set_echo (const bool x); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_echo (const bool echo_on); /**
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
* @param[in] txt true if txt mode
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_sms_txt_mode (const bool txt); /**
* @brief Sets the default (GSM) charater set
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_sms_character_set (); /**
* @brief Sends SMS message in txt mode
* @param[in] number Phone number to send the message to
* @param[in] message Text message to be sent
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_send_sms (const char* number, const char* message); /**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_resume_data_mode (); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Sets php context
* @param[in] x PdP context struct to setup modem cellular connection
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_pdp_context (struct PdpContext* x); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Switches to the command mode
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_command_mode (); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Switches to the CMUX mode
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_cmux (); /**
* @brief Reads the IMSI number
* @param[out] imsi Module's IMSI number
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_imsi (char* imsi); /**
* @brief Reads the IMEI number
* @param[out] imei Module's IMEI number
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_imei (char* imei); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result esp_modem_get_imsi (char* x); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result esp_modem_get_imei (char* x); /**
* @brief Reads the module name
*
* @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_module_name (char* name); /**
* @brief Sets the modem to data mode
*
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_data_mode (); /**
* @brief Get Signal quality
*
*/ command_result esp_modem_get_signal_quality (int* x, int* y);
* @param[out] rssi signal strength indication
* @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_signal_quality (int* rssi, int* ber);

View File

@ -1,5 +1,9 @@
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
// call parametrs by names for documentation
// --- DCE command documentation starts here ---
class esp_modem::DCE: public DCE_T<GenericModule> {
@ -13,51 +17,61 @@ public:
/**
* @brief Sends the supplied PIN code
*
* @param pin Pin
*
*/ command_result set_pin (const std::string& pin); /**
* @brief Sets the supplied PIN code
* @param[in] pin Pin
* @return OK, FAIL or TIMEOUT
*/command_result set_pin (const std::string& pin); /**
* @brief Checks if the SIM needs a PIN
*
* @param[out] pin_ok Pin
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
* @return OK, FAIL or TIMEOUT
*/ command_result read_pin (bool& pin_ok); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result set_echo (const bool x); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
* @return OK, FAIL or TIMEOUT
*/ command_result set_echo (const bool echo_on); /**
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
* @param[in] txt true if txt mode
* @return OK, FAIL or TIMEOUT
*/ command_result sms_txt_mode (const bool txt); /**
* @brief Sets the default (GSM) charater set
* @return OK, FAIL or TIMEOUT
*/ command_result sms_character_set (); /**
* @brief Sends SMS message in txt mode
* @param[in] number Phone number to send the message to
* @param[in] message Text message to be sent
* @return OK, FAIL or TIMEOUT
*/ command_result send_sms (const std::string& number, const std::string& message); /**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ command_result resume_data_mode (); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Sets php context
* @param[in] x PdP context struct to setup modem cellular connection
* @return OK, FAIL or TIMEOUT
*/ command_result set_pdp_context (PdpContext& x); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Switches to the command mode
* @return OK, FAIL or TIMEOUT
*/ command_result set_command_mode (); /**
* @brief Reads the module name
*
* @param[out] name module name
* @brief Switches to the CMUX mode
* @return OK, FAIL or TIMEOUT
*/ command_result set_cmux (); /**
* @brief Reads the IMSI number
* @param[out] imsi Module's IMSI number
* @return OK, FAIL or TIMEOUT
*/ command_result get_imsi (std::string& imsi); /**
* @brief Reads the IMEI number
* @param[out] imei Module's IMEI number
* @return OK, FAIL or TIMEOUT
*/ command_result get_imei (std::string& imei); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result get_imsi (std::string& x); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result get_imei (std::string& x); /**
* @brief Reads the module name
*
* @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ command_result get_module_name (std::string& name); /**
* @brief Sets the modem to data mode
*
* @return OK, FAIL or TIMEOUT
*/ command_result set_data_mode (); /**
* @brief Get Signal quality
*
*/ command_result get_signal_quality (int& x, int& y);
* @param[out] rssi signal strength indication
* @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ command_result get_signal_quality (int& rssi, int& ber);
};

View File

@ -24,7 +24,7 @@ using namespace esp_modem;
static const char *TAG = "cmux_example";
static EventGroupHandle_t event_group = NULL;
static EventGroupHandle_t event_group = nullptr;
static const int CONNECT_BIT = BIT0;
static const int STOP_BIT = BIT1;
static const int GOT_DATA_BIT = BIT2;
@ -141,6 +141,17 @@ extern "C" void app_main(void)
assert(esp_netif);
auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
/// TEST
{
// std::string str;
// dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
// while (1) {
// dce->get_imsi(str);
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
// }
}
// return;
//// TEST
dce->set_command_mode();
std::string str;
@ -163,7 +174,7 @@ extern "C" void app_main(void)
esp_mqtt_client_config_t mqtt_config = { };
mqtt_config.uri = BROKER_URL;
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, nullptr);
esp_mqtt_client_start(mqtt_client);
EventBits_t got_data = 0;
@ -173,13 +184,11 @@ extern "C" void app_main(void)
got_data = xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(500));
}
esp_mqtt_client_destroy(mqtt_client);
dce->get_imsi(str);
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
vTaskDelay(pdMS_TO_TICKS(1000));
while (true) { // reading IMSI number after
dce->get_imsi(str);
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_LOGI(TAG, "Example finished");
}

View File

@ -34,7 +34,7 @@ namespace dce_commands {
/**
* @brief Declaration of all commands is generated from esp_modem_command_declare.inc
*/
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
return_type name(CommandableIf *t, ## __VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);)

View File

@ -95,7 +95,7 @@ class DCE: public DCE_T<GenericModule> {
public:
using DCE_T<GenericModule>::DCE_T;
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
template <typename ...Agrs> \
return_type name(Agrs&&... args) \
{ \

View File

@ -71,7 +71,7 @@ public:
}
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
virtual return_type name(__VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); )

View File

@ -23,7 +23,7 @@ extern "C" {
#endif
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
esp_err_t esp_modem_ ## name(esp_modem_dce_t *dce, ##__VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);)

View File

@ -15,12 +15,11 @@
#ifndef _ESP_MODEM_COMMAND_DECLARE_INC_
#define _ESP_MODEM_COMMAND_DECLARE_INC_
#if GENERATE_DOCS
#define _ARG(param, name) name
#else
#define _ARG(param, name) param
#endif
// Parameters
// * handle different parameters for C++ and C API
// * make parameter unique names, so they could be easily referenced and forwarded
#define _ARG(param, name) param
#ifdef __cplusplus
#include <string>
#define STRING_IN(param, name) const std::string& _ARG(param, name)
@ -39,114 +38,127 @@
#define STRUCT_OUT(struct_name, x) struct struct_name* x
#endif
#define _ESP_MODEM_COMMAND_DECLARE_INC_
#define ESP_MODEM_DEFINE_DCE_COMMAND(...) ESP_MODEM_DECLARE_DCE_COMMAND(##__VA_ARGS__)
#define DEFINE_ALL_COMMAND_APIS() DECLARE_ALL_COMMAND_APIS()
#define DECLARE_ALL_COMMAND_APIS(...) \
/**
* @brief Sends the supplied PIN code
*
* @param pin Pin
*
*/ \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, MUX_ARG, STRING_IN(x, pin)) \
\
* @brief Sets the supplied PIN code
* @param[in] pin Pin
* @return OK, FAIL or TIMEOUT
*/\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(x, pin)) \
\
/**
* @brief Checks if the SIM needs a PIN
*
* @param[out] pin_ok Pin
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, MUX_ARG, BOOL_OUT(x, pin_ok)) \
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, BOOL_OUT(x, pin_ok)) \
\
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, BOOL_IN(x, echo_on)) \
\
/**
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
* @param[in] txt true if txt mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, BOOL_IN(x, txt)) \
\
/**
* @brief Sets the default (GSM) charater set
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0) \
\
/**
* @brief Sends SMS message in txt mode
* @param[in] number Phone number to send the message to
* @param[in] message Text message to be sent
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, STRING_IN(x, number), STRING_IN(y, message)) \
\
/**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0) \
\
/**
* @brief Sets php context
* @param[in] x PdP context struct to setup modem cellular connection
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, STRUCT_OUT(PdpContext, x)) \
\
/**
* @brief Switches to the command mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, 0) \
\
/**
* @brief Switches to the CMUX mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0) \
\
/**
* @brief Reads the IMSI number
* @param[out] imsi Module's IMSI number
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, STRING_OUT(x, imsi)) \
\
/**
* @brief Reads the IMEI number
* @param[out] imei Module's IMEI number
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, STRING_OUT(x, imei)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, MUX_ARG, BOOL_IN(x, echo_on)) \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, MUX_ARG, BOOL_IN(x, txt)) \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0, MUX_ARG) \
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, MUX_ARG, STRING_IN(x, number), STRING_IN(y, message)) \
\
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0, MUX_ARG) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, MUX_ARG, STRUCT_OUT(PdpContext, x)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, 0, MUX_ARG) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0, MUX_ARG) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, MUX_ARG, STRING_OUT(x, imsi)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, MUX_ARG, STRING_OUT(x, name)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, MUX_ARG, STRING_OUT(x, name)) \
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, STRING_OUT(x, name)) \
\
/**
* @brief Sets the modem to data mode
*
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0, MUX_ARG) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0) \
\
/**
* @brief Get Signal quality
*
* @param[out] rssi signal strength indication
* @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, MUX_ARG, INT_OUT(x, rssi), INT_OUT(y, ber))
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x, rssi), INT_OUT(y, ber))
#ifdef GENERATE_DOCS
// cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p'
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
// call parametrs by names for documentation
#undef _ARG
#define _ARG(param, name) name
// --- DCE command documentation starts here ---
#ifdef __cplusplus
class esp_modem::DCE: public DCE_T<GenericModule> {
public:
using DCE_T<GenericModule>::DCE_T;
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) return_type name (__VA_ARGS__);
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type name (__VA_ARGS__);
#elif defined(GENERATE_RST_LINKS)
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) NL- :cpp:func:`esp_modem::DCE::name`
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) NL- :cpp:func:`esp_modem::DCE::name`
#else
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) return_type esp_modem_ ## name (__VA_ARGS__);
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type esp_modem_ ## name (__VA_ARGS__);
#endif
DECLARE_ALL_COMMAND_APIS()

View File

@ -18,10 +18,8 @@
#include "esp_log.h"
#include "cxx_include/esp_modem_api.hpp"
#include "cxx_include/esp_modem_dce_factory.hpp"
#include "esp_modem_c_api_types.h"
#include "esp_modem_config.h"
#include "exception_stub.hpp"
#include "cstring"
namespace esp_modem {

View File

@ -103,24 +103,43 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
}
ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_DEBUG);
uint8_t* frame = data;
uint8_t* recover_ptr;
auto available_len = actual_len;
size_t payload_offset = 0;
size_t footer_offset = 0;
while (available_len > 0) {
switch (state) {
case cmux_state::RECOVER:
// TODO: Implement recovery, looking for SOF_MARKER's
break;
if (frame[0] == SOF_MARKER) {
// already init state
state = cmux_state::INIT;
break;
}
recover_ptr = static_cast<uint8_t*>(memchr(frame, SOF_MARKER, available_len));
if (recover_ptr && available_len > recover_ptr - frame) {
available_len -= (recover_ptr - frame);
frame = recover_ptr;
state = cmux_state::INIT;
ESP_LOGD("CMUX", "Protocol recovered");
if (available_len > 1 && frame[1] == SOF_MARKER) {
// empty frame
available_len -= 1;
frame += 1;
}
break;
}
// marker not found, continue with recovery
return false;
case cmux_state::INIT:
if (frame[0] != SOF_MARKER) {
ESP_LOGW("CMUX", "TODO: Recover!");
return true;
ESP_LOGI("CMUX", "Protocol mismatch!");
state = cmux_state::RECOVER;
break;
}
if (available_len > 1 && frame[1] == SOF_MARKER) {
ESP_LOGI("CMUX", "Empty frame");
// empty frame
available_len -= 2;
frame += 2;
available_len -= 1;
frame += 1;
break;
}
state = cmux_state::HEADER;
@ -140,7 +159,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
dlci = frame_header[1] >> 2;
type = frame_header[2];
payload_len = (frame_header[3] >> 1);
ESP_LOGI("CMUX", "CMUX FR: A:%02x T:%02x L:%d", dlci, type, payload_len);
ESP_LOGD("CMUX", "CMUX FR: A:%02x T:%02x L:%d", dlci, type, payload_len);
frame += payload_offset;
available_len -= payload_offset;
state = cmux_state::PAYLOAD;
@ -169,8 +188,9 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
footer_offset = std::min(available_len, 6 - frame_header_offset);
memcpy(frame_header + frame_header_offset, frame, footer_offset);
if (frame_header[5] != SOF_MARKER) {
ESP_LOGW("CMUX", "TODO: Recover!");
return true;
ESP_LOGI("CMUX", "Protocol mismatch!");
state = cmux_state::RECOVER;
break;
}
if (payload_len == 0) {
data_available(frame_header, 0); // Null payload
@ -190,6 +210,7 @@ void CMux::init()
frame_header_offset = 0;
state = cmux_state::INIT;
term->set_read_cb([this](uint8_t *data, size_t len) {
Scoped<Lock> l(lock);
this->on_cmux(data, len);
return false;
});
@ -203,22 +224,31 @@ void CMux::init()
int CMux::write(int virtual_term, uint8_t *data, size_t len)
{
const size_t cmux_max_len = 127;
Scoped<Lock> l(lock);
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 - fcs_crc(frame);
frame[5] = SOF_MARKER;
size_t need_write = len;
while (need_write > 0) {
size_t batch_len = need_write;
if (batch_len > cmux_max_len)
batch_len = cmux_max_len;
uint8_t frame[6];
frame[0] = SOF_MARKER;
frame[1] = (i << 2) + 1;
frame[2] = FT_UIH;
frame[3] = (batch_len << 1) + 1;
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_VERBOSE);
ESP_LOG_BUFFER_HEXDUMP("Send", data, len, ESP_LOG_VERBOSE);
ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_VERBOSE);
term->write(frame, 4);
term->write(data, batch_len);
term->write(frame + 4, 2);
ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_VERBOSE);
ESP_LOG_BUFFER_HEXDUMP("Send", data, batch_len, ESP_LOG_VERBOSE);
ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_VERBOSE);
need_write -= batch_len;
data += batch_len;
}
return len;
}

View File

@ -28,7 +28,7 @@ GenericModule::GenericModule(std::shared_ptr<DTE> dte, const dce_config *config)
#define _ARGS(x) ARGS ## x
#define ARGS(x) _ARGS(x)
#define TEMPLATE_ARG
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, MUX_ARG, ...) \
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, ...) \
return_type GenericModule::name(__VA_ARGS__) { return esp_modem::dce_commands::name(dte.get() ARGS(arg_nr) ); }
DECLARE_ALL_COMMAND_APIS(return_type name(...) {

View File

@ -95,6 +95,11 @@ void Netif::stop() {
}
Netif::~Netif() {
if (signal.is_any(PPP_STARTED)) {
esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr);
signal.clear(PPP_STARTED);
signal.wait(PPP_EXIT, 30000);
}
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected);