2021-03-29 19:34:45 +02:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
2022-10-11 16:31:57 +02:00
|
|
|
*
|
2021-03-29 19:34:45 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2021-03-24 21:06:27 +01:00
|
|
|
|
2022-06-05 15:43:56 +02:00
|
|
|
#include <list>
|
2022-05-10 17:55:55 +02:00
|
|
|
#include <unistd.h>
|
2022-06-05 15:43:56 +02:00
|
|
|
#include <cstring>
|
2022-05-10 17:55:55 +02:00
|
|
|
|
2021-03-24 21:06:27 +01:00
|
|
|
#include "cxx_include/esp_modem_dte.hpp"
|
|
|
|
#include "cxx_include/esp_modem_dce.hpp"
|
|
|
|
#include "esp_log.h"
|
|
|
|
|
2021-03-29 19:34:45 +02:00
|
|
|
namespace esp_modem {
|
2021-03-24 21:06:27 +01:00
|
|
|
|
2022-10-25 15:41:48 +02:00
|
|
|
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
|
|
|
|
|
2022-06-08 17:16:15 +02:00
|
|
|
/**
|
|
|
|
* Set mode while the entire DTE is locked
|
|
|
|
*/
|
2021-03-29 19:34:45 +02:00
|
|
|
bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m)
|
2022-06-08 17:16:15 +02:00
|
|
|
{
|
|
|
|
Scoped<DTE> lock(*dte);
|
|
|
|
return set_unsafe(dte, device, netif, m);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* state machine:
|
|
|
|
*
|
|
|
|
* COMMAND_MODE <----> DATA_MODE
|
|
|
|
* COMMAND_MODE <----> CMUX_MODE
|
|
|
|
*
|
|
|
|
* UNDEF <----> any
|
|
|
|
*/
|
|
|
|
bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m)
|
2021-03-24 21:06:27 +01:00
|
|
|
{
|
|
|
|
switch (m) {
|
2021-06-01 10:21:51 +02:00
|
|
|
case modem_mode::UNDEF:
|
|
|
|
break;
|
2022-10-25 15:41:48 +02:00
|
|
|
case modem_mode::COMMAND_MODE:
|
|
|
|
if (mode == modem_mode::COMMAND_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
|
2022-06-05 15:43:56 +02:00
|
|
|
return false;
|
|
|
|
}
|
2022-05-26 17:31:22 +02:00
|
|
|
if (mode == modem_mode::CMUX_MODE) {
|
2022-06-05 15:43:56 +02:00
|
|
|
netif.stop();
|
|
|
|
netif.wait_until_ppp_exits();
|
|
|
|
if (!dte->set_mode(modem_mode::COMMAND_MODE)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
mode = m;
|
|
|
|
return true;
|
2021-06-01 10:21:51 +02:00
|
|
|
}
|
2022-10-25 15:41:48 +02:00
|
|
|
if (!transitions::exit_data(*dte, *device, netif)) {
|
2022-06-05 15:43:56 +02:00
|
|
|
mode = modem_mode::UNDEF;
|
|
|
|
return false;
|
2022-10-11 16:31:57 +02:00
|
|
|
}
|
2022-06-05 15:43:56 +02:00
|
|
|
mode = m;
|
|
|
|
return true;
|
2021-06-01 10:21:51 +02:00
|
|
|
case modem_mode::DATA_MODE:
|
2022-10-25 15:41:48 +02:00
|
|
|
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
|
2021-06-01 10:21:51 +02:00
|
|
|
return false;
|
|
|
|
}
|
2022-10-25 15:41:48 +02:00
|
|
|
if (!transitions::enter_data(*dte, *device, netif)) {
|
2021-06-01 10:21:51 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
mode = m;
|
|
|
|
return true;
|
|
|
|
case modem_mode::CMUX_MODE:
|
2022-10-25 15:41:48 +02:00
|
|
|
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE || mode >= modem_mode::CMUX_MANUAL_MODE) {
|
2021-06-01 10:21:51 +02:00
|
|
|
return false;
|
|
|
|
}
|
2022-05-10 17:55:55 +02:00
|
|
|
device->set_mode(modem_mode::CMUX_MODE); // switch the device into CMUX mode
|
2022-06-10 18:04:10 +02:00
|
|
|
usleep(100'000); // some devices need a few ms to switch
|
2022-05-10 17:55:55 +02:00
|
|
|
|
2021-06-01 10:21:51 +02:00
|
|
|
if (!dte->set_mode(modem_mode::CMUX_MODE)) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-05-26 17:31:22 +02:00
|
|
|
mode = modem_mode::CMUX_MODE;
|
2022-10-25 15:41:48 +02:00
|
|
|
return transitions::enter_data(*dte, *device, netif);
|
|
|
|
case modem_mode::CMUX_MANUAL_MODE:
|
2022-10-25 16:50:34 +02:00
|
|
|
if (mode != modem_mode::COMMAND_MODE && mode != modem_mode::UNDEF) {
|
2022-10-25 15:41:48 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
device->set_mode(modem_mode::CMUX_MODE);
|
|
|
|
usleep(100'000);
|
|
|
|
|
|
|
|
if (!dte->set_mode(m)) {
|
2022-05-26 17:31:22 +02:00
|
|
|
return false;
|
|
|
|
}
|
2022-10-25 15:41:48 +02:00
|
|
|
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) {
|
2022-05-26 17:31:22 +02:00
|
|
|
return false;
|
|
|
|
}
|
2022-10-25 15:41:48 +02:00
|
|
|
if (!dte->set_mode(m)) {
|
2022-05-26 17:31:22 +02:00
|
|
|
return false;
|
|
|
|
}
|
2021-06-01 10:21:51 +02:00
|
|
|
return true;
|
2022-10-25 15:41:48 +02:00
|
|
|
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);
|
2021-03-24 21:06:27 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-03-29 19:34:45 +02:00
|
|
|
modem_mode DCE_Mode::get()
|
2021-03-24 21:06:27 +01:00
|
|
|
{
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
|
2021-03-29 19:34:45 +02:00
|
|
|
} // esp_modem
|