feat(esp-modem): Add support for manual CMUX operations

Closes https://github.com/espressif/esp-protocols/issues/168
This commit is contained in:
David Cermak
2022-10-25 15:41:48 +02:00
parent 3f0262dfe5
commit ac5d43882b
7 changed files with 185 additions and 87 deletions

View File

@ -14,6 +14,59 @@
namespace esp_modem {
namespace transitions {
static bool exit_data(DTE &dte, ModuleIf &device, Netif &netif)
{
netif.stop();
auto signal = std::make_shared<SignalGroup>();
std::weak_ptr<SignalGroup> weak_signal = signal;
dte.set_read_cb([weak_signal](uint8_t *data, size_t len) -> bool {
if (memchr(data, '\n', len))
{
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, len, ESP_LOG_DEBUG);
const auto pass = std::list<std::string_view>({"NO CARRIER", "DISCONNECTED"});
std::string_view response((char *) data, len);
for (auto &it : pass)
if (response.find(it) != std::string::npos) {
if (auto signal = weak_signal.lock()) {
signal->set(1);
}
return true;
}
}
return false;
});
netif.wait_until_ppp_exits();
if (!signal->wait(1, 2000)) {
if (!device.set_mode(modem_mode::COMMAND_MODE)) {
return false;
}
}
dte.set_read_cb(nullptr);
if (!dte.set_mode(modem_mode::COMMAND_MODE)) {
return false;
}
return true;
}
static bool enter_data(DTE &dte, ModuleIf &device, Netif &netif)
{
if (!device.setup_data_mode()) {
return false;
}
if (!device.set_mode(modem_mode::DATA_MODE)) {
return false;
}
if (!dte.set_mode(modem_mode::DATA_MODE)) {
return false;
}
netif.start();
return true;
}
} // namespace transitions
/**
* Set mode while the entire DTE is locked
*/
@ -36,8 +89,8 @@ bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m
switch (m) {
case modem_mode::UNDEF:
break;
case modem_mode::COMMAND_MODE: {
if (mode == modem_mode::COMMAND_MODE) {
case modem_mode::COMMAND_MODE:
if (mode == modem_mode::COMMAND_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
return false;
}
if (mode == modem_mode::CMUX_MODE) {
@ -49,59 +102,23 @@ bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m
mode = m;
return true;
}
netif.stop();
auto signal = std::make_shared<SignalGroup>();
std::weak_ptr<SignalGroup> weak_signal = signal;
dte->set_read_cb([weak_signal](uint8_t *data, size_t len) -> bool {
if (memchr(data, '\n', len))
{
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, len, ESP_LOG_DEBUG);
const auto pass = std::list<std::string_view>({"NO CARRIER", "DISCONNECTED"});
std::string_view response((char *) data, len);
for (auto &it : pass)
if (response.find(it) != std::string::npos) {
if (auto signal = weak_signal.lock()) {
signal->set(1);
}
return true;
}
}
return false;
});
netif.wait_until_ppp_exits();
if (!signal->wait(1, 2000)) {
if (!device->set_mode(modem_mode::COMMAND_MODE)) {
mode = modem_mode::UNDEF;
return false;
}
}
dte->set_read_cb(nullptr);
if (!dte->set_mode(modem_mode::COMMAND_MODE)) {
if (!transitions::exit_data(*dte, *device, netif)) {
mode = modem_mode::UNDEF;
return false;
}
mode = m;
return true;
}
break;
case modem_mode::DATA_MODE:
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE) {
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
return false;
}
if (!device->setup_data_mode()) {
if (!transitions::enter_data(*dte, *device, netif)) {
return false;
}
if (!device->set_mode(modem_mode::DATA_MODE)) {
return false;
}
if (!dte->set_mode(modem_mode::DATA_MODE)) {
return false;
}
netif.start();
mode = m;
return true;
case modem_mode::CMUX_MODE:
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE) {
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
return false;
}
device->set_mode(modem_mode::CMUX_MODE); // switch the device into CMUX mode
@ -111,17 +128,46 @@ bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m
return false;
}
mode = modem_mode::CMUX_MODE;
if (!device->setup_data_mode()) {
return transitions::enter_data(*dte, *device, netif);
case modem_mode::CMUX_MANUAL_MODE:
if (mode != modem_mode::COMMAND_MODE) {
return false;
}
if (!device->set_mode(modem_mode::DATA_MODE)) {
device->set_mode(modem_mode::CMUX_MODE);
usleep(100'000);
if (!dte->set_mode(m)) {
return false;
}
if (!dte->set_mode(modem_mode::DATA_MODE)) {
return false;
}
netif.start();
mode = modem_mode::CMUX_MANUAL_MODE;
return true;
case modem_mode::CMUX_MANUAL_EXIT:
if (mode != modem_mode::CMUX_MANUAL_MODE) {
return false;
}
if (!dte->set_mode(m)) {
return false;
}
mode = modem_mode::COMMAND_MODE;
return true;
case modem_mode::CMUX_MANUAL_SWAP:
if (mode != modem_mode::CMUX_MANUAL_MODE) {
return false;
}
if (!dte->set_mode(m)) {
return false;
}
return true;
case modem_mode::CMUX_MANUAL_DATA:
if (mode != modem_mode::CMUX_MANUAL_MODE) {
return false;
}
return transitions::enter_data(*dte, *device, netif);
case modem_mode::CMUX_MANUAL_COMMAND:
if (mode != modem_mode::CMUX_MANUAL_MODE) {
return false;
}
return transitions::exit_data(*dte, *device, netif);
}
return false;
}