Skip to content

Commit c43a380

Browse files
author
Veijo Pesonen
committed
Enables TCP passive mode if FW v1.7 or later
1 parent 97cc8c1 commit c43a380

File tree

3 files changed

+118
-26
lines changed

3 files changed

+118
-26
lines changed

ESP8266/ESP8266.cpp

Lines changed: 90 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
3030
_serial_rts(rts),
3131
_serial_cts(cts),
3232
_parser(&_serial),
33+
_tcp_passive(false),
3334
_packets(0),
3435
_packets_end(&_packets),
3536
_sdk_v(-1,-1,-1),
3637
_at_v(-1,-1,-1),
3738
_connect_error(0),
3839
_fail(false),
3940
_closed(false),
40-
_socket_open(),
4141
_connection_status(NSAPI_STATUS_DISCONNECTED),
4242
_heap_usage(0)
4343
{
@@ -57,6 +57,11 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
5757
_parser.oob("4,CLOSED", callback(this, &ESP8266::_oob_socket4_closed_handler));
5858
_parser.oob("WIFI ", callback(this, &ESP8266::_connection_status_handler));
5959
_parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_error));
60+
61+
for(int i= 0; i < SOCKET_COUNT; i++) {
62+
_socket_open[i].id = -1;
63+
_socket_open[i].proto = NSAPI_UDP;
64+
}
6065
}
6166

6267
bool ESP8266::at_available()
@@ -76,9 +81,9 @@ struct ESP8266::fw_sdk_version ESP8266::sdk_version()
7681
int patch;
7782

7883
_smutex.lock();
79-
bool done = _parser.send("AT+GMR");
80-
done &= _parser.recv("SDK version:%d.%d.%d", &major, &minor, &patch);
81-
done &= _parser.recv("OK\n");
84+
bool done = _parser.send("AT+GMR")
85+
&& _parser.recv("SDK version:%d.%d.%d", &major, &minor, &patch)
86+
&& _parser.recv("OK\n");
8287
_smutex.unlock();
8388

8489
if(done) {
@@ -97,9 +102,9 @@ struct ESP8266::fw_at_version ESP8266::at_version()
97102
int nused;
98103

99104
_smutex.lock();
100-
bool done = _parser.send("AT+GMR");
101-
done &= _parser.recv("AT version:%d.%d.%d.%d", &major, &minor, &patch, &nused);
102-
done &= _parser.recv("OK\n");
105+
bool done = _parser.send("AT+GMR")
106+
&& _parser.recv("AT version:%d.%d.%d.%d", &major, &minor, &patch, &nused)
107+
&& _parser.recv("OK\n");
103108
_smutex.unlock();
104109

105110
if(done) {
@@ -210,6 +215,23 @@ bool ESP8266::dhcp(bool enabled, int mode)
210215
return done;
211216
}
212217

218+
bool ESP8266::cond_enable_tcp_passive_mode()
219+
{
220+
bool done = true;
221+
222+
if (FW_AT_LEAST_VERSION(_at_v.major, _at_v.minor, _at_v.patch, 0, ESP8266_AT_VERSION_TCP_PASSIVE_MODE)) {
223+
_smutex.lock();
224+
done = _parser.send("AT+CIPRECVMODE=1")
225+
&& _parser.recv("OK\n");
226+
_smutex.unlock();
227+
228+
_tcp_passive = done ? true : false;
229+
}
230+
231+
return done;
232+
}
233+
234+
213235
nsapi_error_t ESP8266::connect(const char *ap, const char *passPhrase)
214236
{
215237
_smutex.lock();
@@ -376,7 +398,7 @@ nsapi_error_t ESP8266::open_udp(int id, const char* addr, int port, int local_po
376398

377399
if (id >= SOCKET_COUNT) {
378400
return NSAPI_ERROR_PARAMETER;
379-
} else if (_socket_open[id]) {
401+
} else if (_socket_open[id].id == id) {
380402
return NSAPI_ERROR_IS_CONNECTED;
381403
}
382404

@@ -390,7 +412,8 @@ nsapi_error_t ESP8266::open_udp(int id, const char* addr, int port, int local_po
390412
}
391413

392414
if (done) {
393-
_socket_open[id] = 1;
415+
_socket_open[id].id = id;
416+
_socket_open[id].proto = NSAPI_UDP;
394417
}
395418

396419
_clear_socket_packets(id);
@@ -405,7 +428,7 @@ bool ESP8266::open_tcp(int id, const char* addr, int port, int keepalive)
405428
static const char *type = "TCP";
406429
bool done = false;
407430

408-
if (id >= SOCKET_COUNT || _socket_open[id]) {
431+
if (id >= SOCKET_COUNT || _socket_open[id].id == id) {
409432
return false;
410433
}
411434

@@ -419,7 +442,8 @@ bool ESP8266::open_tcp(int id, const char* addr, int port, int keepalive)
419442
}
420443

421444
if (done) {
422-
_socket_open[id] = 1;
445+
_socket_open[id].id = id;
446+
_socket_open[id].proto = NSAPI_TCP;
423447
}
424448

425449
_clear_socket_packets(id);
@@ -467,8 +491,21 @@ void ESP8266::_packet_handler()
467491
int amount;
468492
int pdu_len;
469493

470-
// parse out the packet
471-
if (!_parser.recv(",%d,%d:", &id, &amount)) {
494+
// Get socket id
495+
if (!_parser.recv(",%d,", &id)) {
496+
return;
497+
}
498+
// In passive mode amount not used...
499+
if(_tcp_passive
500+
&& _socket_open[id].id == id
501+
&& _socket_open[id].proto == NSAPI_TCP) {
502+
if (!_parser.recv("%d\n", &amount)) {
503+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENODATA), \
504+
"ESP8266::_packet_handler(): Data length missing");
505+
}
506+
return;
507+
// Amount required in active mode
508+
} else if (!_parser.recv("%d:", &amount)) {
472509
return;
473510
}
474511

@@ -512,8 +549,41 @@ void ESP8266::process_oob(uint32_t timeout, bool all) {
512549
setTimeout();
513550
}
514551

552+
int32_t ESP8266::_recv_tcp_passive(int id, void *data, uint32_t amount, uint32_t timeout)
553+
{
554+
int32_t len;
555+
int32_t ret;
556+
557+
_smutex.lock();
558+
559+
bool done = _parser.send("AT+CIPRECVDATA=%d,%lu", id, amount);
560+
if (!done) {
561+
_smutex.unlock();
562+
return NSAPI_ERROR_DEVICE_ERROR;
563+
}
564+
// NOTE: documentation v3.0 says '+CIPRECVDATA:<data_len>,' but it's not how the FW responds...
565+
done = _parser.recv("+CIPRECVDATA,%ld:", &len)
566+
&& _parser.read((char*)data, len)
567+
&& _parser.recv("OK\n");
568+
569+
// Got data?
570+
if (done) {
571+
ret = len;
572+
} else {
573+
// Socket still open?
574+
ret = _socket_open[id].id != id ? 0 : (int32_t)NSAPI_ERROR_WOULD_BLOCK;
575+
}
576+
577+
_smutex.unlock();
578+
return ret;
579+
}
580+
515581
int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout)
516582
{
583+
if (_tcp_passive) {
584+
return _recv_tcp_passive(id, data, amount, timeout);
585+
}
586+
517587
_smutex.lock();
518588

519589
// No flow control, drain the USART receive register ASAP to avoid data overrun
@@ -552,7 +622,7 @@ int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout)
552622
}
553623
}
554624
}
555-
if(!_socket_open[id]) {
625+
if(_socket_open[id].id < 0) {
556626
_smutex.unlock();
557627
return 0;
558628
}
@@ -634,7 +704,7 @@ bool ESP8266::close(int id)
634704
if (!_parser.recv("OK\n")) {
635705
if (_closed) { // UNLINK ERROR
636706
_closed = false;
637-
_socket_open[id] = 0;
707+
_socket_open[id].id = -1;
638708
_clear_socket_packets(id);
639709
_smutex.unlock();
640710
// ESP8266 has a habit that it might close a socket on its own.
@@ -717,27 +787,27 @@ void ESP8266::_oob_socket_close_error()
717787

718788
void ESP8266::_oob_socket0_closed_handler()
719789
{
720-
_socket_open[0] = 0;
790+
_socket_open[0].id = -1;
721791
}
722792

723793
void ESP8266::_oob_socket1_closed_handler()
724794
{
725-
_socket_open[1] = 0;
795+
_socket_open[1].id = -1;
726796
}
727797

728798
void ESP8266::_oob_socket2_closed_handler()
729799
{
730-
_socket_open[2] = 0;
800+
_socket_open[2].id = -1;
731801
}
732802

733803
void ESP8266::_oob_socket3_closed_handler()
734804
{
735-
_socket_open[3] = 0;
805+
_socket_open[3].id = -1;
736806
}
737807

738808
void ESP8266::_oob_socket4_closed_handler()
739809
{
740-
_socket_open[4] = 0;
810+
_socket_open[4].id = -1;
741811
}
742812

743813
void ESP8266::_connection_status_handler()

ESP8266/ESP8266.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@
3535
#define ESP8266_MISC_TIMEOUT 2000
3636
#endif
3737

38+
// Firmware version
39+
#define ESP8266_SDK_VERSION 2000000
40+
#define ESP8266_SDK_VERSION_MAJOR ESP8266_SDK_VERSION/1000000
41+
42+
#define ESP8266_AT_VERSION 1000000
43+
#define ESP8266_AT_VERSION_MAJOR ESP8266_AT_VERSION/1000000
44+
#define ESP8266_AT_VERSION_TCP_PASSIVE_MODE 1070000
45+
46+
#define FW_AT_LEAST_VERSION(MAJOR,MINOR,PATCH,NUSED/*Not used*/,REF) \
47+
(((MAJOR)*1000000+(MINOR)*10000+(PATCH)*100) >= REF ? true : false)
48+
3849
/** ESP8266Interface class.
3950
This is an interface to a ESP8266 radio.
4051
*/
@@ -321,6 +332,11 @@ class ESP8266
321332
*/
322333
bool stop_uart_hw_flow_ctrl();
323334

335+
/*
336+
* From AT firmware v1.7.0.0 onwards enables TCP passive mode
337+
*/
338+
bool cond_enable_tcp_passive_mode();
339+
324340
static const int8_t WIFIMODE_STATION = 1;
325341
static const int8_t WIFIMODE_SOFTAP = 2;
326342
static const int8_t WIFIMODE_STATION_SOFTAP = 3;
@@ -332,6 +348,7 @@ class ESP8266
332348
PinName _serial_cts;
333349
ATCmdParser _parser;
334350
Mutex _smutex; // Protect serial port access
351+
bool _tcp_passive;
335352

336353
struct packet {
337354
struct packet *next;
@@ -355,16 +372,21 @@ class ESP8266
355372
void _oob_socket_close_error();
356373
void _clear_socket_packets(int id);
357374
void process_oob(uint32_t timeout, bool all);
375+
int32_t _recv_tcp_passive(int id, void *data, uint32_t amount, uint32_t timeout);
358376

359377
char _ip_buffer[16];
360378
char _gateway_buffer[16];
361379
char _netmask_buffer[16];
362380
char _mac_buffer[18];
381+
struct _sock_info {
382+
int id;
383+
nsapi_protocol_t proto;
384+
};
363385

364386
int _connect_error;
365387
bool _fail;
366388
bool _closed;
367-
int _socket_open[SOCKET_COUNT];
389+
struct _sock_info _socket_open[SOCKET_COUNT];
368390
nsapi_connection_status_t _connection_status;
369391
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
370392
size_t _heap_usage;

ESP8266Interface.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@
3737
#endif
3838
#endif
3939

40-
// Firmware version
41-
#define ESP8266_SDK_VERSION_MAJOR 2
42-
#define ESP8266_AT_VERSION_MAJOR 1
43-
4440
ESP8266Interface::ESP8266Interface()
4541
: _esp(MBED_CONF_ESP8266_TX, MBED_CONF_ESP8266_RX, MBED_CONF_ESP8266_DEBUG, MBED_CONF_ESP8266_RTS, MBED_CONF_ESP8266_CTS),
4642
_initialized(false),
@@ -290,9 +286,13 @@ nsapi_error_t ESP8266Interface::_init(void)
290286
if (!_get_firmware_ok()) {
291287
return NSAPI_ERROR_DEVICE_ERROR;
292288
}
293-
if (_disable_default_softap() == false) {
289+
if (!_disable_default_softap()) {
290+
return NSAPI_ERROR_DEVICE_ERROR;
291+
}
292+
if (!_esp.cond_enable_tcp_passive_mode()) {
294293
return NSAPI_ERROR_DEVICE_ERROR;
295294
}
295+
296296
_initialized = true;
297297
}
298298
return NSAPI_ERROR_OK;

0 commit comments

Comments
 (0)