Skip to content

Commit 2180ab1

Browse files
committed
fix(esp-modem): Support AT with callback in C-API
Closes #143
1 parent ac5d438 commit 2180ab1

File tree

5 files changed

+65
-44
lines changed

5 files changed

+65
-44
lines changed

components/esp_modem/include/cxx_include/esp_modem_dte.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ class DTE : public CommandableIf {
116116
Lock internal_lock{}; /*!< Locks DTE operations */
117117
unique_buffer buffer; /*!< DTE buffer */
118118
std::shared_ptr<CMux> cmux_term; /*!< Primary terminal for this DTE */
119-
std::shared_ptr<Terminal> term; /*!< Reference to the primary terminal (mostly for sending commands) */
120-
std::shared_ptr<Terminal> other_term; /*!< Secondary terminal for this DTE */
119+
std::shared_ptr<Terminal> primary_term; /*!< Reference to the primary terminal (mostly for sending commands) */
120+
std::shared_ptr<Terminal> secondary_term; /*!< Secondary terminal for this DTE */
121121
modem_mode mode; /*!< DTE operation mode */
122122
SignalGroup signal; /*!< Event group used to signal request-response operations */
123123
command_result result; /*!< Command result of the currently exectuted command */

components/esp_modem/include/esp_modem_c_api_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ esp_err_t esp_modem_set_error_cb(esp_modem_dce_t *dce, esp_modem_terminal_error_
118118
*/
119119
esp_err_t esp_modem_set_mode(esp_modem_dce_t *dce, esp_modem_dce_mode_t mode);
120120

121+
esp_err_t esp_modem_command(esp_modem_dce_t *dce, const char *command, esp_err_t(*got_line_cb)(uint8_t *data, size_t len), uint32_t timeout_ms);
122+
121123
/**
122124
* @}
123125
*/

components/esp_modem/src/esp_modem_c_api.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,22 @@ extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t *dce_wrap, esp_modem_dce
9494
return ESP_ERR_INVALID_ARG;
9595
}
9696
switch (mode) {
97-
case ESP_MODEM_MODE_DATA:
98-
return dce_wrap->dce->set_mode(modem_mode::DATA_MODE) ? ESP_OK : ESP_FAIL;
99-
case ESP_MODEM_MODE_COMMAND:
100-
return dce_wrap->dce->set_mode(modem_mode::COMMAND_MODE) ? ESP_OK : ESP_FAIL;
101-
case ESP_MODEM_MODE_CMUX:
102-
return dce_wrap->dce->set_mode(modem_mode::CMUX_MODE) ? ESP_OK : ESP_FAIL;
103-
case ESP_MODEM_MODE_CMUX_MANUAL:
104-
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_MODE) ? ESP_OK : ESP_FAIL;
105-
case ESP_MODEM_MODE_CMUX_MANUAL_EXIT:
106-
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_EXIT) ? ESP_OK : ESP_FAIL;
107-
case ESP_MODEM_MODE_CMUX_MANUAL_SWAP:
108-
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_SWAP) ? ESP_OK : ESP_FAIL;
109-
case ESP_MODEM_MODE_CMUX_MANUAL_DATA:
110-
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_DATA) ? ESP_OK : ESP_FAIL;
111-
case ESP_MODEM_MODE_CMUX_MANUAL_COMMAND:
112-
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND) ? ESP_OK : ESP_FAIL;
97+
case ESP_MODEM_MODE_DATA:
98+
return dce_wrap->dce->set_mode(modem_mode::DATA_MODE) ? ESP_OK : ESP_FAIL;
99+
case ESP_MODEM_MODE_COMMAND:
100+
return dce_wrap->dce->set_mode(modem_mode::COMMAND_MODE) ? ESP_OK : ESP_FAIL;
101+
case ESP_MODEM_MODE_CMUX:
102+
return dce_wrap->dce->set_mode(modem_mode::CMUX_MODE) ? ESP_OK : ESP_FAIL;
103+
case ESP_MODEM_MODE_CMUX_MANUAL:
104+
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_MODE) ? ESP_OK : ESP_FAIL;
105+
case ESP_MODEM_MODE_CMUX_MANUAL_EXIT:
106+
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_EXIT) ? ESP_OK : ESP_FAIL;
107+
case ESP_MODEM_MODE_CMUX_MANUAL_SWAP:
108+
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_SWAP) ? ESP_OK : ESP_FAIL;
109+
case ESP_MODEM_MODE_CMUX_MANUAL_DATA:
110+
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_DATA) ? ESP_OK : ESP_FAIL;
111+
case ESP_MODEM_MODE_CMUX_MANUAL_COMMAND:
112+
return dce_wrap->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND) ? ESP_OK : ESP_FAIL;
113113
}
114114
return ESP_ERR_NOT_SUPPORTED;
115115
}
@@ -400,3 +400,21 @@ extern "C" esp_err_t esp_modem_set_pdp_context(esp_modem_dce_t *dce_wrap, esp_mo
400400
pdp.protocol_type = c_api_pdp->protocol_type;
401401
return command_response_to_esp_err(dce_wrap->dce->set_pdp_context(pdp));
402402
}
403+
404+
extern "C" esp_err_t esp_modem_command(esp_modem_dce_t *dce_wrap, const char *command, esp_err_t(*got_line_fn)(uint8_t *data, size_t len), uint32_t timeout_ms)
405+
{
406+
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || command == nullptr || got_line_fn == nullptr) {
407+
return ESP_ERR_INVALID_ARG;
408+
}
409+
std::string cmd(command);
410+
return command_response_to_esp_err(dce_wrap->dce->command(cmd, [got_line_fn](uint8_t *data, size_t len) {
411+
switch (got_line_fn(data, len)) {
412+
case ESP_OK:
413+
return command_result::OK;
414+
case ESP_FAIL:
415+
return command_result::FAIL;
416+
default:
417+
return command_result::TIMEOUT;
418+
}
419+
}, timeout_ms));
420+
}

components/esp_modem/src/esp_modem_dce.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ bool DCE_Mode::set_unsafe(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m
130130
mode = modem_mode::CMUX_MODE;
131131
return transitions::enter_data(*dte, *device, netif);
132132
case modem_mode::CMUX_MANUAL_MODE:
133-
if (mode != modem_mode::COMMAND_MODE) {
133+
if (mode != modem_mode::COMMAND_MODE && mode != modem_mode::UNDEF) {
134134
return false;
135135
}
136136
device->set_mode(modem_mode::CMUX_MODE);

components/esp_modem/src/esp_modem_dte.cpp

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ using namespace esp_modem;
1515
static const size_t dte_default_buffer_size = 1000;
1616

1717
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> terminal):
18-
buffer(config->dte_buffer_size),
19-
cmux_term(nullptr), term(std::move(terminal)), other_term(term),
20-
mode(modem_mode::UNDEF) {}
18+
buffer(config->dte_buffer_size),
19+
cmux_term(nullptr), primary_term(std::move(terminal)), secondary_term(primary_term),
20+
mode(modem_mode::UNDEF) {}
2121

2222
DTE::DTE(std::unique_ptr<Terminal> terminal):
23-
buffer(dte_default_buffer_size),
24-
cmux_term(nullptr), term(std::move(terminal)), other_term(term),
25-
mode(modem_mode::UNDEF) {}
23+
buffer(dte_default_buffer_size),
24+
cmux_term(nullptr), primary_term(std::move(terminal)), secondary_term(primary_term),
25+
mode(modem_mode::UNDEF) {}
2626

2727
command_result DTE::command(const std::string &command, got_line_cb got_line, uint32_t time_ms, const char separator)
2828
{
2929
Scoped<Lock> l(internal_lock);
3030
result = command_result::TIMEOUT;
3131
signal.clear(GOT_LINE);
32-
term->set_read_cb([this, got_line, separator](uint8_t *data, size_t len) {
32+
primary_term->set_read_cb([this, got_line, separator](uint8_t *data, size_t len) {
3333
if (!data) {
3434
data = buffer.get();
35-
len = term->read(data + buffer.consumed, buffer.size - buffer.consumed);
35+
len = primary_term->read(data + buffer.consumed, buffer.size - buffer.consumed);
3636
} else {
3737
buffer.consumed = 0; // if the underlying terminal contains data, we cannot fragment
3838
}
@@ -46,13 +46,13 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
4646
buffer.consumed += len;
4747
return false;
4848
});
49-
term->write((uint8_t *)command.c_str(), command.length());
49+
primary_term->write((uint8_t *)command.c_str(), command.length());
5050
auto got_lf = signal.wait(GOT_LINE, time_ms);
5151
if (got_lf && result == command_result::TIMEOUT) {
5252
ESP_MODEM_THROW_IF_ERROR(ESP_ERR_INVALID_STATE);
5353
}
5454
buffer.consumed = 0;
55-
term->set_read_cb(nullptr);
55+
primary_term->set_read_cb(nullptr);
5656
return result;
5757
}
5858

@@ -68,26 +68,26 @@ bool DTE::exit_cmux()
6868
}
6969
auto ejected = cmux_term->detach();
7070
// return the ejected terminal and buffer back to this DTE
71-
term = std::move(ejected.first);
71+
primary_term = std::move(ejected.first);
7272
buffer = std::move(ejected.second);
73-
other_term = term;
73+
secondary_term = primary_term;
7474
return true;
7575
}
7676

7777
bool DTE::setup_cmux()
7878
{
79-
cmux_term = std::make_shared<CMux>(term, std::move(buffer));
79+
cmux_term = std::make_shared<CMux>(primary_term, std::move(buffer));
8080
if (cmux_term == nullptr) {
8181
return false;
8282
}
8383
if (!cmux_term->init()) {
8484
return false;
8585
}
86-
term = std::make_unique<CMuxInstance>(cmux_term, 0);
87-
if (term == nullptr) {
86+
primary_term = std::make_unique<CMuxInstance>(cmux_term, 0);
87+
if (primary_term == nullptr) {
8888
return false;
8989
}
90-
other_term = std::make_unique<CMuxInstance>(cmux_term, 1);
90+
secondary_term = std::make_unique<CMuxInstance>(cmux_term, 1);
9191
return true;
9292
}
9393

@@ -108,7 +108,7 @@ bool DTE::set_mode(modem_mode m)
108108
if (m == modem_mode::DATA_MODE) {
109109
if (mode == modem_mode::CMUX_MODE || mode == modem_mode::CMUX_MANUAL_MODE) {
110110
// mode stays the same, but need to swap terminals (as command has been switched)
111-
other_term.swap(term);
111+
secondary_term.swap(primary_term);
112112
} else {
113113
mode = m;
114114
}
@@ -150,19 +150,20 @@ bool DTE::set_mode(modem_mode m)
150150
}
151151
// manual CMUX transitions: Swap terminals
152152
if (m == modem_mode::CMUX_MANUAL_SWAP && mode == modem_mode::CMUX_MANUAL_MODE) {
153-
other_term.swap(term);
153+
secondary_term.swap(primary_term);
154154
return true;
155155
}
156-
return true;
156+
mode = modem_mode::UNDEF;
157+
return false;
157158
}
158159

159160
void DTE::set_read_cb(std::function<bool(uint8_t *, size_t)> f)
160161
{
161162
on_data = std::move(f);
162-
other_term->set_read_cb([this](uint8_t *data, size_t len) {
163+
secondary_term->set_read_cb([this](uint8_t *data, size_t len) {
163164
if (!data) { // if no data available from terminal callback -> need to explicitly read some
164165
data = buffer.get();
165-
len = other_term->read(buffer.get(), buffer.size);
166+
len = secondary_term->read(buffer.get(), buffer.size);
166167
}
167168
if (on_data) {
168169
return on_data(data, len);
@@ -173,22 +174,22 @@ void DTE::set_read_cb(std::function<bool(uint8_t *, size_t)> f)
173174

174175
void DTE::set_error_cb(std::function<void(terminal_error err)> f)
175176
{
176-
other_term->set_error_cb(f);
177-
term->set_error_cb(f);
177+
secondary_term->set_error_cb(f);
178+
primary_term->set_error_cb(f);
178179
}
179180

180181
int DTE::read(uint8_t **d, size_t len)
181182
{
182183
auto data_to_read = std::min(len, buffer.size);
183184
auto data = buffer.get();
184-
auto actual_len = other_term->read(data, data_to_read);
185+
auto actual_len = secondary_term->read(data, data_to_read);
185186
*d = data;
186187
return actual_len;
187188
}
188189

189190
int DTE::write(uint8_t *data, size_t len)
190191
{
191-
return other_term->write(data, len);
192+
return secondary_term->write(data, len);
192193
}
193194

194195
/**

0 commit comments

Comments
 (0)