Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* ESP8266 implementation of NetworkInterfaceAPI
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2015 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 5 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 6 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 7 *
kenjiArai 0:5b88d5760320 8 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 9 *
kenjiArai 0:5b88d5760320 10 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 11 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 13 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 14 * limitations under the License.
kenjiArai 0:5b88d5760320 15 */
kenjiArai 0:5b88d5760320 16
kenjiArai 0:5b88d5760320 17 #if DEVICE_SERIAL && DEVICE_INTERRUPTIN && defined(MBED_CONF_EVENTS_PRESENT) && defined(MBED_CONF_NSAPI_PRESENT) && defined(MBED_CONF_RTOS_PRESENT)
kenjiArai 0:5b88d5760320 18
kenjiArai 0:5b88d5760320 19 #include <string.h>
kenjiArai 0:5b88d5760320 20 #include <stdint.h>
kenjiArai 0:5b88d5760320 21
kenjiArai 0:5b88d5760320 22 #include "ESP8266.h"
kenjiArai 0:5b88d5760320 23 #include "ESP8266Interface.h"
kenjiArai 0:5b88d5760320 24 #include "events/EventQueue.h"
kenjiArai 0:5b88d5760320 25 #include "events/mbed_shared_queues.h"
kenjiArai 0:5b88d5760320 26 #include "features/netsocket/nsapi_types.h"
kenjiArai 0:5b88d5760320 27 #include "mbed_trace.h"
kenjiArai 0:5b88d5760320 28 #include "platform/Callback.h"
kenjiArai 0:5b88d5760320 29 #include "platform/mbed_atomic.h"
kenjiArai 0:5b88d5760320 30 #include "platform/mbed_debug.h"
kenjiArai 0:5b88d5760320 31 #include "platform/mbed_wait_api.h"
kenjiArai 0:5b88d5760320 32
kenjiArai 0:5b88d5760320 33 #ifndef MBED_CONF_ESP8266_DEBUG
kenjiArai 0:5b88d5760320 34 #define MBED_CONF_ESP8266_DEBUG false
kenjiArai 0:5b88d5760320 35 #endif
kenjiArai 0:5b88d5760320 36
kenjiArai 0:5b88d5760320 37 #ifndef MBED_CONF_ESP8266_RTS
kenjiArai 0:5b88d5760320 38 #define MBED_CONF_ESP8266_RTS NC
kenjiArai 0:5b88d5760320 39 #endif
kenjiArai 0:5b88d5760320 40
kenjiArai 0:5b88d5760320 41 #ifndef MBED_CONF_ESP8266_CTS
kenjiArai 0:5b88d5760320 42 #define MBED_CONF_ESP8266_CTS NC
kenjiArai 0:5b88d5760320 43 #endif
kenjiArai 0:5b88d5760320 44
kenjiArai 0:5b88d5760320 45 #ifndef MBED_CONF_ESP8266_RST
kenjiArai 0:5b88d5760320 46 #define MBED_CONF_ESP8266_RST NC
kenjiArai 0:5b88d5760320 47 #endif
kenjiArai 0:5b88d5760320 48
kenjiArai 0:5b88d5760320 49 #define TRACE_GROUP "ESPI" // ESP8266 Interface
kenjiArai 0:5b88d5760320 50
kenjiArai 0:5b88d5760320 51 using namespace mbed;
kenjiArai 0:5b88d5760320 52
kenjiArai 0:5b88d5760320 53 #if defined MBED_CONF_ESP8266_TX && defined MBED_CONF_ESP8266_RX
kenjiArai 0:5b88d5760320 54 ESP8266Interface::ESP8266Interface()
kenjiArai 0:5b88d5760320 55 : _esp(MBED_CONF_ESP8266_TX, MBED_CONF_ESP8266_RX, MBED_CONF_ESP8266_DEBUG, MBED_CONF_ESP8266_RTS, MBED_CONF_ESP8266_CTS),
kenjiArai 0:5b88d5760320 56 _rst_pin(MBED_CONF_ESP8266_RST), // Notice that Pin7 CH_EN cannot be left floating if used as reset
kenjiArai 0:5b88d5760320 57 _ap_sec(NSAPI_SECURITY_UNKNOWN),
kenjiArai 0:5b88d5760320 58 _if_blocking(true),
kenjiArai 0:5b88d5760320 59 _if_connected(_cmutex),
kenjiArai 0:5b88d5760320 60 _initialized(false),
kenjiArai 0:5b88d5760320 61 _connect_retval(NSAPI_ERROR_OK),
kenjiArai 0:5b88d5760320 62 _conn_stat(NSAPI_STATUS_DISCONNECTED),
kenjiArai 0:5b88d5760320 63 _conn_stat_cb(NULL),
kenjiArai 0:5b88d5760320 64 _global_event_queue(mbed_event_queue()), // Needs to be set before attaching event() to SIGIO
kenjiArai 0:5b88d5760320 65 _oob_event_id(0),
kenjiArai 0:5b88d5760320 66 _connect_event_id(0)
kenjiArai 0:5b88d5760320 67 {
kenjiArai 0:5b88d5760320 68 memset(_cbs, 0, sizeof(_cbs));
kenjiArai 0:5b88d5760320 69 memset(ap_ssid, 0, sizeof(ap_ssid));
kenjiArai 0:5b88d5760320 70 memset(ap_pass, 0, sizeof(ap_pass));
kenjiArai 0:5b88d5760320 71
kenjiArai 0:5b88d5760320 72 _ch_info.track_ap = true;
kenjiArai 0:5b88d5760320 73 strncpy(_ch_info.country_code, MBED_CONF_ESP8266_COUNTRY_CODE, sizeof(_ch_info.country_code));
kenjiArai 0:5b88d5760320 74 _ch_info.channel_start = MBED_CONF_ESP8266_CHANNEL_START;
kenjiArai 0:5b88d5760320 75 _ch_info.channels = MBED_CONF_ESP8266_CHANNELS;
kenjiArai 0:5b88d5760320 76
kenjiArai 0:5b88d5760320 77 _esp.sigio(this, &ESP8266Interface::event);
kenjiArai 0:5b88d5760320 78 _esp.set_timeout();
kenjiArai 0:5b88d5760320 79 _esp.attach(this, &ESP8266Interface::refresh_conn_state_cb);
kenjiArai 0:5b88d5760320 80
kenjiArai 0:5b88d5760320 81 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
kenjiArai 0:5b88d5760320 82 _sock_i[i].open = false;
kenjiArai 0:5b88d5760320 83 _sock_i[i].sport = 0;
kenjiArai 0:5b88d5760320 84 }
kenjiArai 0:5b88d5760320 85 }
kenjiArai 0:5b88d5760320 86 #endif
kenjiArai 0:5b88d5760320 87
kenjiArai 0:5b88d5760320 88 // ESP8266Interface implementation
kenjiArai 0:5b88d5760320 89 ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName rts, PinName cts, PinName rst)
kenjiArai 0:5b88d5760320 90 : _esp(tx, rx, debug, rts, cts),
kenjiArai 0:5b88d5760320 91 _rst_pin(rst),
kenjiArai 0:5b88d5760320 92 _ap_sec(NSAPI_SECURITY_UNKNOWN),
kenjiArai 0:5b88d5760320 93 _if_blocking(true),
kenjiArai 0:5b88d5760320 94 _if_connected(_cmutex),
kenjiArai 0:5b88d5760320 95 _initialized(false),
kenjiArai 0:5b88d5760320 96 _conn_stat(NSAPI_STATUS_DISCONNECTED),
kenjiArai 0:5b88d5760320 97 _conn_stat_cb(NULL),
kenjiArai 0:5b88d5760320 98 _global_event_queue(mbed_event_queue()), // Needs to be set before attaching event() to SIGIO
kenjiArai 0:5b88d5760320 99 _oob_event_id(0),
kenjiArai 0:5b88d5760320 100 _connect_event_id(0)
kenjiArai 0:5b88d5760320 101 {
kenjiArai 0:5b88d5760320 102 memset(_cbs, 0, sizeof(_cbs));
kenjiArai 0:5b88d5760320 103 memset(ap_ssid, 0, sizeof(ap_ssid));
kenjiArai 0:5b88d5760320 104 memset(ap_pass, 0, sizeof(ap_pass));
kenjiArai 0:5b88d5760320 105
kenjiArai 0:5b88d5760320 106 _ch_info.track_ap = true;
kenjiArai 0:5b88d5760320 107 strncpy(_ch_info.country_code, MBED_CONF_ESP8266_COUNTRY_CODE, sizeof(_ch_info.country_code));
kenjiArai 0:5b88d5760320 108 _ch_info.channel_start = MBED_CONF_ESP8266_CHANNEL_START;
kenjiArai 0:5b88d5760320 109 _ch_info.channels = MBED_CONF_ESP8266_CHANNELS;
kenjiArai 0:5b88d5760320 110
kenjiArai 0:5b88d5760320 111 _esp.sigio(this, &ESP8266Interface::event);
kenjiArai 0:5b88d5760320 112 _esp.set_timeout();
kenjiArai 0:5b88d5760320 113 _esp.attach(this, &ESP8266Interface::refresh_conn_state_cb);
kenjiArai 0:5b88d5760320 114
kenjiArai 0:5b88d5760320 115 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
kenjiArai 0:5b88d5760320 116 _sock_i[i].open = false;
kenjiArai 0:5b88d5760320 117 _sock_i[i].sport = 0;
kenjiArai 0:5b88d5760320 118 }
kenjiArai 0:5b88d5760320 119 }
kenjiArai 0:5b88d5760320 120
kenjiArai 0:5b88d5760320 121 ESP8266Interface::~ESP8266Interface()
kenjiArai 0:5b88d5760320 122 {
kenjiArai 0:5b88d5760320 123 if (_oob_event_id) {
kenjiArai 0:5b88d5760320 124 _global_event_queue->cancel(_oob_event_id);
kenjiArai 0:5b88d5760320 125 }
kenjiArai 0:5b88d5760320 126
kenjiArai 0:5b88d5760320 127 _cmutex.lock();
kenjiArai 0:5b88d5760320 128 if (_connect_event_id) {
kenjiArai 0:5b88d5760320 129 _global_event_queue->cancel(_connect_event_id);
kenjiArai 0:5b88d5760320 130 }
kenjiArai 0:5b88d5760320 131 _cmutex.unlock();
kenjiArai 0:5b88d5760320 132
kenjiArai 0:5b88d5760320 133 // Power down the modem
kenjiArai 0:5b88d5760320 134 _rst_pin.rst_assert();
kenjiArai 0:5b88d5760320 135 }
kenjiArai 0:5b88d5760320 136
kenjiArai 0:5b88d5760320 137 ESP8266Interface::ResetPin::ResetPin(PinName rst_pin) : _rst_pin(mbed::DigitalOut(rst_pin, 1))
kenjiArai 0:5b88d5760320 138 {
kenjiArai 0:5b88d5760320 139 }
kenjiArai 0:5b88d5760320 140
kenjiArai 0:5b88d5760320 141 void ESP8266Interface::ResetPin::rst_assert()
kenjiArai 0:5b88d5760320 142 {
kenjiArai 0:5b88d5760320 143 if (_rst_pin.is_connected()) {
kenjiArai 0:5b88d5760320 144 _rst_pin = 0;
kenjiArai 0:5b88d5760320 145 tr_debug("HW reset asserted");
kenjiArai 0:5b88d5760320 146 }
kenjiArai 0:5b88d5760320 147 }
kenjiArai 0:5b88d5760320 148
kenjiArai 0:5b88d5760320 149 void ESP8266Interface::ResetPin::rst_deassert()
kenjiArai 0:5b88d5760320 150 {
kenjiArai 0:5b88d5760320 151 if (_rst_pin.is_connected()) {
kenjiArai 0:5b88d5760320 152 // Notice that Pin7 CH_EN cannot be left floating if used as reset
kenjiArai 0:5b88d5760320 153 _rst_pin = 1;
kenjiArai 0:5b88d5760320 154 tr_debug("HW reset deasserted");
kenjiArai 0:5b88d5760320 155 }
kenjiArai 0:5b88d5760320 156 }
kenjiArai 0:5b88d5760320 157
kenjiArai 0:5b88d5760320 158 bool ESP8266Interface::ResetPin::is_connected()
kenjiArai 0:5b88d5760320 159 {
kenjiArai 0:5b88d5760320 160 return _rst_pin.is_connected();
kenjiArai 0:5b88d5760320 161 }
kenjiArai 0:5b88d5760320 162
kenjiArai 0:5b88d5760320 163 int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
kenjiArai 0:5b88d5760320 164 uint8_t channel)
kenjiArai 0:5b88d5760320 165 {
kenjiArai 0:5b88d5760320 166 if (channel != 0) {
kenjiArai 0:5b88d5760320 167 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 168 }
kenjiArai 0:5b88d5760320 169
kenjiArai 0:5b88d5760320 170 int err = set_credentials(ssid, pass, security);
kenjiArai 0:5b88d5760320 171 if (err) {
kenjiArai 0:5b88d5760320 172 return err;
kenjiArai 0:5b88d5760320 173 }
kenjiArai 0:5b88d5760320 174
kenjiArai 0:5b88d5760320 175 return connect();
kenjiArai 0:5b88d5760320 176 }
kenjiArai 0:5b88d5760320 177
kenjiArai 0:5b88d5760320 178 void ESP8266Interface::_connect_async()
kenjiArai 0:5b88d5760320 179 {
kenjiArai 0:5b88d5760320 180 _cmutex.lock();
kenjiArai 0:5b88d5760320 181 if (!_connect_event_id) {
kenjiArai 0:5b88d5760320 182 tr_debug("_connect_async(): cancelled");
kenjiArai 0:5b88d5760320 183 _cmutex.unlock();
kenjiArai 0:5b88d5760320 184 return;
kenjiArai 0:5b88d5760320 185 }
kenjiArai 0:5b88d5760320 186 _connect_retval = _esp.connect(ap_ssid, ap_pass);
kenjiArai 0:5b88d5760320 187 int timeleft_ms = ESP8266_INTERFACE_CONNECT_TIMEOUT_MS - _conn_timer.read_ms();
kenjiArai 0:5b88d5760320 188 if (_connect_retval == NSAPI_ERROR_OK || _connect_retval == NSAPI_ERROR_AUTH_FAILURE
kenjiArai 0:5b88d5760320 189 || _connect_retval == NSAPI_ERROR_NO_SSID
kenjiArai 0:5b88d5760320 190 || ((_if_blocking == true) && (timeleft_ms <= 0))) {
kenjiArai 0:5b88d5760320 191 _connect_event_id = 0;
kenjiArai 0:5b88d5760320 192 _conn_timer.stop();
kenjiArai 0:5b88d5760320 193 if (timeleft_ms <= 0) {
kenjiArai 0:5b88d5760320 194 _connect_retval = NSAPI_ERROR_CONNECTION_TIMEOUT;
kenjiArai 0:5b88d5760320 195 }
kenjiArai 0:5b88d5760320 196 _if_connected.notify_all();
kenjiArai 0:5b88d5760320 197 } else {
kenjiArai 0:5b88d5760320 198 // Postpone to give other stuff time to run
kenjiArai 0:5b88d5760320 199 _connect_event_id = _global_event_queue->call_in(ESP8266_INTERFACE_CONNECT_INTERVAL_MS,
kenjiArai 0:5b88d5760320 200 callback(this, &ESP8266Interface::_connect_async));
kenjiArai 0:5b88d5760320 201 if (!_connect_event_id) {
kenjiArai 0:5b88d5760320 202 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
kenjiArai 0:5b88d5760320 203 "ESP8266Interface::_connect_async(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
kenjiArai 0:5b88d5760320 204 }
kenjiArai 0:5b88d5760320 205 }
kenjiArai 0:5b88d5760320 206 _cmutex.unlock();
kenjiArai 0:5b88d5760320 207 }
kenjiArai 0:5b88d5760320 208
kenjiArai 0:5b88d5760320 209 int ESP8266Interface::connect()
kenjiArai 0:5b88d5760320 210 {
kenjiArai 0:5b88d5760320 211 nsapi_error_t status = _conn_status_to_error();
kenjiArai 0:5b88d5760320 212 if (status != NSAPI_ERROR_NO_CONNECTION) {
kenjiArai 0:5b88d5760320 213 return status;
kenjiArai 0:5b88d5760320 214 }
kenjiArai 0:5b88d5760320 215
kenjiArai 0:5b88d5760320 216 if (strlen(ap_ssid) == 0) {
kenjiArai 0:5b88d5760320 217 return NSAPI_ERROR_NO_SSID;
kenjiArai 0:5b88d5760320 218 }
kenjiArai 0:5b88d5760320 219
kenjiArai 0:5b88d5760320 220 if (_ap_sec != NSAPI_SECURITY_NONE) {
kenjiArai 0:5b88d5760320 221 if (strlen(ap_pass) < ESP8266_PASSPHRASE_MIN_LENGTH) {
kenjiArai 0:5b88d5760320 222 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 223 }
kenjiArai 0:5b88d5760320 224 }
kenjiArai 0:5b88d5760320 225
kenjiArai 0:5b88d5760320 226 status = _init();
kenjiArai 0:5b88d5760320 227 if (status != NSAPI_ERROR_OK) {
kenjiArai 0:5b88d5760320 228 return status;
kenjiArai 0:5b88d5760320 229 }
kenjiArai 0:5b88d5760320 230
kenjiArai 0:5b88d5760320 231 if (get_ip_address()) {
kenjiArai 0:5b88d5760320 232 return NSAPI_ERROR_IS_CONNECTED;
kenjiArai 0:5b88d5760320 233 }
kenjiArai 0:5b88d5760320 234
kenjiArai 0:5b88d5760320 235 if (!_esp.dhcp(true, 1)) {
kenjiArai 0:5b88d5760320 236 return NSAPI_ERROR_DHCP_FAILURE;
kenjiArai 0:5b88d5760320 237 }
kenjiArai 0:5b88d5760320 238
kenjiArai 0:5b88d5760320 239 _cmutex.lock();
kenjiArai 0:5b88d5760320 240
kenjiArai 0:5b88d5760320 241 _connect_retval = NSAPI_ERROR_NO_CONNECTION;
kenjiArai 0:5b88d5760320 242 MBED_ASSERT(!_connect_event_id);
kenjiArai 0:5b88d5760320 243 _conn_timer.stop();
kenjiArai 0:5b88d5760320 244 _conn_timer.reset();
kenjiArai 0:5b88d5760320 245 _conn_timer.start();
kenjiArai 0:5b88d5760320 246 _connect_event_id = _global_event_queue->call(callback(this, &ESP8266Interface::_connect_async));
kenjiArai 0:5b88d5760320 247
kenjiArai 0:5b88d5760320 248 if (!_connect_event_id) {
kenjiArai 0:5b88d5760320 249 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
kenjiArai 0:5b88d5760320 250 "connect(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
kenjiArai 0:5b88d5760320 251 }
kenjiArai 0:5b88d5760320 252
kenjiArai 0:5b88d5760320 253 while (_if_blocking && (_conn_status_to_error() != NSAPI_ERROR_IS_CONNECTED)
kenjiArai 0:5b88d5760320 254 && (_connect_retval == NSAPI_ERROR_NO_CONNECTION)) {
kenjiArai 0:5b88d5760320 255 _if_connected.wait();
kenjiArai 0:5b88d5760320 256 }
kenjiArai 0:5b88d5760320 257
kenjiArai 0:5b88d5760320 258 _cmutex.unlock();
kenjiArai 0:5b88d5760320 259
kenjiArai 0:5b88d5760320 260 if (!_if_blocking) {
kenjiArai 0:5b88d5760320 261 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 262 } else {
kenjiArai 0:5b88d5760320 263 return _connect_retval;
kenjiArai 0:5b88d5760320 264 }
kenjiArai 0:5b88d5760320 265 }
kenjiArai 0:5b88d5760320 266
kenjiArai 0:5b88d5760320 267 int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
kenjiArai 0:5b88d5760320 268 {
kenjiArai 0:5b88d5760320 269 nsapi_error_t status = _conn_status_to_error();
kenjiArai 0:5b88d5760320 270 if (status != NSAPI_ERROR_NO_CONNECTION) {
kenjiArai 0:5b88d5760320 271 return status;
kenjiArai 0:5b88d5760320 272 }
kenjiArai 0:5b88d5760320 273
kenjiArai 0:5b88d5760320 274 _ap_sec = security;
kenjiArai 0:5b88d5760320 275
kenjiArai 0:5b88d5760320 276 if (!ssid) {
kenjiArai 0:5b88d5760320 277 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 278 }
kenjiArai 0:5b88d5760320 279
kenjiArai 0:5b88d5760320 280 int ssid_length = strlen(ssid);
kenjiArai 0:5b88d5760320 281
kenjiArai 0:5b88d5760320 282 if (ssid_length > 0
kenjiArai 0:5b88d5760320 283 && ssid_length <= ESP8266_SSID_MAX_LENGTH) {
kenjiArai 0:5b88d5760320 284 memset(ap_ssid, 0, sizeof(ap_ssid));
kenjiArai 0:5b88d5760320 285 strncpy(ap_ssid, ssid, sizeof(ap_ssid));
kenjiArai 0:5b88d5760320 286 } else {
kenjiArai 0:5b88d5760320 287 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 288 }
kenjiArai 0:5b88d5760320 289
kenjiArai 0:5b88d5760320 290 if (_ap_sec != NSAPI_SECURITY_NONE) {
kenjiArai 0:5b88d5760320 291
kenjiArai 0:5b88d5760320 292 if (!pass) {
kenjiArai 0:5b88d5760320 293 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 294 }
kenjiArai 0:5b88d5760320 295
kenjiArai 0:5b88d5760320 296 int pass_length = strlen(pass);
kenjiArai 0:5b88d5760320 297 if (pass_length >= ESP8266_PASSPHRASE_MIN_LENGTH
kenjiArai 0:5b88d5760320 298 && pass_length <= ESP8266_PASSPHRASE_MAX_LENGTH) {
kenjiArai 0:5b88d5760320 299 memset(ap_pass, 0, sizeof(ap_pass));
kenjiArai 0:5b88d5760320 300 strncpy(ap_pass, pass, sizeof(ap_pass));
kenjiArai 0:5b88d5760320 301 } else {
kenjiArai 0:5b88d5760320 302 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 303 }
kenjiArai 0:5b88d5760320 304 } else {
kenjiArai 0:5b88d5760320 305 memset(ap_pass, 0, sizeof(ap_pass));
kenjiArai 0:5b88d5760320 306 }
kenjiArai 0:5b88d5760320 307
kenjiArai 0:5b88d5760320 308 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 309 }
kenjiArai 0:5b88d5760320 310
kenjiArai 0:5b88d5760320 311 int ESP8266Interface::set_channel(uint8_t channel)
kenjiArai 0:5b88d5760320 312 {
kenjiArai 0:5b88d5760320 313 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 314 }
kenjiArai 0:5b88d5760320 315
kenjiArai 0:5b88d5760320 316
kenjiArai 0:5b88d5760320 317 int ESP8266Interface::disconnect()
kenjiArai 0:5b88d5760320 318 {
kenjiArai 0:5b88d5760320 319 _cmutex.lock();
kenjiArai 0:5b88d5760320 320 if (_connect_event_id) {
kenjiArai 0:5b88d5760320 321 _global_event_queue->cancel(_connect_event_id);
kenjiArai 0:5b88d5760320 322 _connect_event_id = 0; // cancel asynchronous connection attempt if one is ongoing
kenjiArai 0:5b88d5760320 323 }
kenjiArai 0:5b88d5760320 324 _cmutex.unlock();
kenjiArai 0:5b88d5760320 325 _initialized = false;
kenjiArai 0:5b88d5760320 326
kenjiArai 0:5b88d5760320 327 nsapi_error_t status = _conn_status_to_error();
kenjiArai 0:5b88d5760320 328 if (status == NSAPI_ERROR_NO_CONNECTION) {
kenjiArai 0:5b88d5760320 329 return NSAPI_ERROR_NO_CONNECTION;
kenjiArai 0:5b88d5760320 330 }
kenjiArai 0:5b88d5760320 331
kenjiArai 0:5b88d5760320 332 int ret = _esp.disconnect() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 333
kenjiArai 0:5b88d5760320 334 if (ret == NSAPI_ERROR_OK) {
kenjiArai 0:5b88d5760320 335 // Try to lure the nw status update from ESP8266, might come later
kenjiArai 0:5b88d5760320 336 _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
kenjiArai 0:5b88d5760320 337 // In case the status update arrives later inform upper layers manually
kenjiArai 0:5b88d5760320 338 if (_conn_stat != NSAPI_STATUS_DISCONNECTED) {
kenjiArai 0:5b88d5760320 339 _conn_stat = NSAPI_STATUS_DISCONNECTED;
kenjiArai 0:5b88d5760320 340 if (_conn_stat_cb) {
kenjiArai 0:5b88d5760320 341 _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
kenjiArai 0:5b88d5760320 342 }
kenjiArai 0:5b88d5760320 343 }
kenjiArai 0:5b88d5760320 344 }
kenjiArai 0:5b88d5760320 345
kenjiArai 0:5b88d5760320 346 // Power down the modem
kenjiArai 0:5b88d5760320 347 _rst_pin.rst_assert();
kenjiArai 0:5b88d5760320 348
kenjiArai 0:5b88d5760320 349 return ret;
kenjiArai 0:5b88d5760320 350 }
kenjiArai 0:5b88d5760320 351
kenjiArai 0:5b88d5760320 352 const char *ESP8266Interface::get_ip_address()
kenjiArai 0:5b88d5760320 353 {
kenjiArai 0:5b88d5760320 354 const char *ip_buff = _esp.ip_addr();
kenjiArai 0:5b88d5760320 355 if (!ip_buff || strcmp(ip_buff, "0.0.0.0") == 0) {
kenjiArai 0:5b88d5760320 356 return NULL;
kenjiArai 0:5b88d5760320 357 }
kenjiArai 0:5b88d5760320 358
kenjiArai 0:5b88d5760320 359 return ip_buff;
kenjiArai 0:5b88d5760320 360 }
kenjiArai 0:5b88d5760320 361
kenjiArai 0:5b88d5760320 362 const char *ESP8266Interface::get_mac_address()
kenjiArai 0:5b88d5760320 363 {
kenjiArai 0:5b88d5760320 364 return _esp.mac_addr();
kenjiArai 0:5b88d5760320 365 }
kenjiArai 0:5b88d5760320 366
kenjiArai 0:5b88d5760320 367 const char *ESP8266Interface::get_gateway()
kenjiArai 0:5b88d5760320 368 {
kenjiArai 0:5b88d5760320 369 return _conn_stat != NSAPI_STATUS_DISCONNECTED ? _esp.gateway() : NULL;
kenjiArai 0:5b88d5760320 370 }
kenjiArai 0:5b88d5760320 371
kenjiArai 0:5b88d5760320 372 const char *ESP8266Interface::get_netmask()
kenjiArai 0:5b88d5760320 373 {
kenjiArai 0:5b88d5760320 374 return _conn_stat != NSAPI_STATUS_DISCONNECTED ? _esp.netmask() : NULL;
kenjiArai 0:5b88d5760320 375 }
kenjiArai 0:5b88d5760320 376
kenjiArai 0:5b88d5760320 377 int8_t ESP8266Interface::get_rssi()
kenjiArai 0:5b88d5760320 378 {
kenjiArai 0:5b88d5760320 379 return _esp.rssi();
kenjiArai 0:5b88d5760320 380 }
kenjiArai 0:5b88d5760320 381
kenjiArai 0:5b88d5760320 382 int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count)
kenjiArai 0:5b88d5760320 383 {
kenjiArai 0:5b88d5760320 384 return scan(res, count, SCANMODE_ACTIVE, 0, 0);
kenjiArai 0:5b88d5760320 385 }
kenjiArai 0:5b88d5760320 386
kenjiArai 0:5b88d5760320 387 int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count, scan_mode mode, unsigned t_max, unsigned t_min)
kenjiArai 0:5b88d5760320 388 {
kenjiArai 0:5b88d5760320 389 if (t_max > ESP8266_SCAN_TIME_MAX) {
kenjiArai 0:5b88d5760320 390 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 391 }
kenjiArai 0:5b88d5760320 392 if (mode == SCANMODE_ACTIVE && t_min > t_max) {
kenjiArai 0:5b88d5760320 393 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 394 }
kenjiArai 0:5b88d5760320 395
kenjiArai 0:5b88d5760320 396 nsapi_error_t status = _init();
kenjiArai 0:5b88d5760320 397 if (status != NSAPI_ERROR_OK) {
kenjiArai 0:5b88d5760320 398 return status;
kenjiArai 0:5b88d5760320 399 }
kenjiArai 0:5b88d5760320 400
kenjiArai 0:5b88d5760320 401 return _esp.scan(res, count, (mode == SCANMODE_ACTIVE ? ESP8266::SCANMODE_ACTIVE : ESP8266::SCANMODE_PASSIVE),
kenjiArai 0:5b88d5760320 402 t_min, t_max);
kenjiArai 0:5b88d5760320 403 }
kenjiArai 0:5b88d5760320 404
kenjiArai 0:5b88d5760320 405 bool ESP8266Interface::_get_firmware_ok()
kenjiArai 0:5b88d5760320 406 {
kenjiArai 0:5b88d5760320 407 ESP8266::fw_at_version at_v = _esp.at_version();
kenjiArai 0:5b88d5760320 408 if (at_v.major < ESP8266_AT_VERSION_MAJOR) {
kenjiArai 0:5b88d5760320 409 debug("ESP8266: ERROR: AT Firmware v%d incompatible with this driver.", at_v.major);
kenjiArai 0:5b88d5760320 410 debug("Update at least to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\n", ESP8266_AT_VERSION_MAJOR);
kenjiArai 0:5b88d5760320 411 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_UNSUPPORTED), "Too old AT firmware");
kenjiArai 0:5b88d5760320 412 }
kenjiArai 0:5b88d5760320 413 ESP8266::fw_sdk_version sdk_v = _esp.sdk_version();
kenjiArai 0:5b88d5760320 414 if (sdk_v.major < ESP8266_SDK_VERSION_MAJOR) {
kenjiArai 0:5b88d5760320 415 debug("ESP8266: ERROR: Firmware v%d incompatible with this driver.", sdk_v.major);
kenjiArai 0:5b88d5760320 416 debug("Update at least to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\n", ESP8266_SDK_VERSION_MAJOR);
kenjiArai 0:5b88d5760320 417 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_UNSUPPORTED), "Too old SDK firmware");
kenjiArai 0:5b88d5760320 418 }
kenjiArai 0:5b88d5760320 419
kenjiArai 0:5b88d5760320 420 return true;
kenjiArai 0:5b88d5760320 421 }
kenjiArai 0:5b88d5760320 422
kenjiArai 0:5b88d5760320 423 nsapi_error_t ESP8266Interface::_init(void)
kenjiArai 0:5b88d5760320 424 {
kenjiArai 0:5b88d5760320 425 if (!_initialized) {
kenjiArai 0:5b88d5760320 426 if (_reset() != NSAPI_ERROR_OK) {
kenjiArai 0:5b88d5760320 427 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 428 }
kenjiArai 0:5b88d5760320 429 if (!_esp.echo_off()) {
kenjiArai 0:5b88d5760320 430 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 431 }
kenjiArai 0:5b88d5760320 432 if (!_esp.start_uart_hw_flow_ctrl()) {
kenjiArai 0:5b88d5760320 433 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 434 }
kenjiArai 0:5b88d5760320 435 if (!_get_firmware_ok()) {
kenjiArai 0:5b88d5760320 436 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 437 }
kenjiArai 0:5b88d5760320 438 if (!_esp.set_default_wifi_mode(ESP8266::WIFIMODE_STATION)) {
kenjiArai 0:5b88d5760320 439 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 440 }
kenjiArai 0:5b88d5760320 441 if (!_esp.set_country_code_policy(true, _ch_info.country_code, _ch_info.channel_start, _ch_info.channels)) {
kenjiArai 0:5b88d5760320 442 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 443 }
kenjiArai 0:5b88d5760320 444 if (!_esp.cond_enable_tcp_passive_mode()) {
kenjiArai 0:5b88d5760320 445 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 446 }
kenjiArai 0:5b88d5760320 447 if (!_esp.startup(ESP8266::WIFIMODE_STATION)) {
kenjiArai 0:5b88d5760320 448 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 449 }
kenjiArai 0:5b88d5760320 450
kenjiArai 0:5b88d5760320 451 _initialized = true;
kenjiArai 0:5b88d5760320 452 }
kenjiArai 0:5b88d5760320 453 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 454 }
kenjiArai 0:5b88d5760320 455
kenjiArai 0:5b88d5760320 456 nsapi_error_t ESP8266Interface::_reset()
kenjiArai 0:5b88d5760320 457 {
kenjiArai 0:5b88d5760320 458 if (_rst_pin.is_connected()) {
kenjiArai 0:5b88d5760320 459 _rst_pin.rst_assert();
kenjiArai 0:5b88d5760320 460 // If you happen to use Pin7 CH_EN as reset pin, not needed otherwise
kenjiArai 0:5b88d5760320 461 // https://www.espressif.com/sites/default/files/documentation/esp8266_hardware_design_guidelines_en.pdf
kenjiArai 0:5b88d5760320 462 wait_ms(2); // Documentation says 200 us should have been enough, but experimentation shows that 1ms was not enough
kenjiArai 0:5b88d5760320 463 _esp.flush();
kenjiArai 0:5b88d5760320 464 _rst_pin.rst_deassert();
kenjiArai 0:5b88d5760320 465 } else {
kenjiArai 0:5b88d5760320 466 _esp.flush();
kenjiArai 0:5b88d5760320 467 if (!_esp.at_available()) {
kenjiArai 0:5b88d5760320 468 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 469 }
kenjiArai 0:5b88d5760320 470 if (!_esp.reset()) {
kenjiArai 0:5b88d5760320 471 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 472 }
kenjiArai 0:5b88d5760320 473 }
kenjiArai 0:5b88d5760320 474
kenjiArai 0:5b88d5760320 475 return _esp.at_available() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 476 }
kenjiArai 0:5b88d5760320 477
kenjiArai 0:5b88d5760320 478 struct esp8266_socket {
kenjiArai 0:5b88d5760320 479 int id;
kenjiArai 0:5b88d5760320 480 nsapi_protocol_t proto;
kenjiArai 0:5b88d5760320 481 bool connected;
kenjiArai 0:5b88d5760320 482 SocketAddress addr;
kenjiArai 0:5b88d5760320 483 int keepalive; // TCP
kenjiArai 0:5b88d5760320 484 };
kenjiArai 0:5b88d5760320 485
kenjiArai 0:5b88d5760320 486 int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
kenjiArai 0:5b88d5760320 487 {
kenjiArai 0:5b88d5760320 488 // Look for an unused socket
kenjiArai 0:5b88d5760320 489 int id = -1;
kenjiArai 0:5b88d5760320 490
kenjiArai 0:5b88d5760320 491 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
kenjiArai 0:5b88d5760320 492 if (!_sock_i[i].open) {
kenjiArai 0:5b88d5760320 493 id = i;
kenjiArai 0:5b88d5760320 494 _sock_i[i].open = true;
kenjiArai 0:5b88d5760320 495 break;
kenjiArai 0:5b88d5760320 496 }
kenjiArai 0:5b88d5760320 497 }
kenjiArai 0:5b88d5760320 498
kenjiArai 0:5b88d5760320 499 if (id == -1) {
kenjiArai 0:5b88d5760320 500 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 501 }
kenjiArai 0:5b88d5760320 502
kenjiArai 0:5b88d5760320 503 struct esp8266_socket *socket = new struct esp8266_socket;
kenjiArai 0:5b88d5760320 504 if (!socket) {
kenjiArai 0:5b88d5760320 505 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 506 }
kenjiArai 0:5b88d5760320 507
kenjiArai 0:5b88d5760320 508 socket->id = id;
kenjiArai 0:5b88d5760320 509 socket->proto = proto;
kenjiArai 0:5b88d5760320 510 socket->connected = false;
kenjiArai 0:5b88d5760320 511 socket->keepalive = 0;
kenjiArai 0:5b88d5760320 512 *handle = socket;
kenjiArai 0:5b88d5760320 513 return 0;
kenjiArai 0:5b88d5760320 514 }
kenjiArai 0:5b88d5760320 515
kenjiArai 0:5b88d5760320 516 int ESP8266Interface::socket_close(void *handle)
kenjiArai 0:5b88d5760320 517 {
kenjiArai 0:5b88d5760320 518 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 519 int err = 0;
kenjiArai 0:5b88d5760320 520
kenjiArai 0:5b88d5760320 521 if (!socket) {
kenjiArai 0:5b88d5760320 522 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 523 }
kenjiArai 0:5b88d5760320 524
kenjiArai 0:5b88d5760320 525 if (socket->connected && !_esp.close(socket->id)) {
kenjiArai 0:5b88d5760320 526 err = NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 527 }
kenjiArai 0:5b88d5760320 528
kenjiArai 0:5b88d5760320 529 _cbs[socket->id].callback = NULL;
kenjiArai 0:5b88d5760320 530 _cbs[socket->id].data = NULL;
kenjiArai 0:5b88d5760320 531 core_util_atomic_store_u8(&_cbs[socket->id].deferred, false);
kenjiArai 0:5b88d5760320 532
kenjiArai 0:5b88d5760320 533 socket->connected = false;
kenjiArai 0:5b88d5760320 534 _sock_i[socket->id].open = false;
kenjiArai 0:5b88d5760320 535 _sock_i[socket->id].sport = 0;
kenjiArai 0:5b88d5760320 536 delete socket;
kenjiArai 0:5b88d5760320 537 return err;
kenjiArai 0:5b88d5760320 538 }
kenjiArai 0:5b88d5760320 539
kenjiArai 0:5b88d5760320 540 int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
kenjiArai 0:5b88d5760320 541 {
kenjiArai 0:5b88d5760320 542 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 543
kenjiArai 0:5b88d5760320 544 if (!socket) {
kenjiArai 0:5b88d5760320 545 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 546 }
kenjiArai 0:5b88d5760320 547
kenjiArai 0:5b88d5760320 548 if (socket->proto == NSAPI_UDP) {
kenjiArai 0:5b88d5760320 549 if (address.get_addr().version != NSAPI_UNSPEC) {
kenjiArai 0:5b88d5760320 550 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 551 }
kenjiArai 0:5b88d5760320 552
kenjiArai 0:5b88d5760320 553 for (int id = 0; id < ESP8266_SOCKET_COUNT; id++) {
kenjiArai 0:5b88d5760320 554 if (_sock_i[id].sport == address.get_port() && id != socket->id) { // Port already reserved by another socket
kenjiArai 0:5b88d5760320 555 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 556 } else if (id == socket->id && socket->connected) {
kenjiArai 0:5b88d5760320 557 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 558 }
kenjiArai 0:5b88d5760320 559 }
kenjiArai 0:5b88d5760320 560 _sock_i[socket->id].sport = address.get_port();
kenjiArai 0:5b88d5760320 561 return 0;
kenjiArai 0:5b88d5760320 562 }
kenjiArai 0:5b88d5760320 563
kenjiArai 0:5b88d5760320 564 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 565 }
kenjiArai 0:5b88d5760320 566
kenjiArai 0:5b88d5760320 567 int ESP8266Interface::socket_listen(void *handle, int backlog)
kenjiArai 0:5b88d5760320 568 {
kenjiArai 0:5b88d5760320 569 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 570 }
kenjiArai 0:5b88d5760320 571
kenjiArai 0:5b88d5760320 572 int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
kenjiArai 0:5b88d5760320 573 {
kenjiArai 0:5b88d5760320 574 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 575 nsapi_error_t ret;
kenjiArai 0:5b88d5760320 576
kenjiArai 0:5b88d5760320 577 if (!socket) {
kenjiArai 0:5b88d5760320 578 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 579 }
kenjiArai 0:5b88d5760320 580
kenjiArai 0:5b88d5760320 581 if (socket->proto == NSAPI_UDP) {
kenjiArai 0:5b88d5760320 582 ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _sock_i[socket->id].sport);
kenjiArai 0:5b88d5760320 583 } else {
kenjiArai 0:5b88d5760320 584 ret = _esp.open_tcp(socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive);
kenjiArai 0:5b88d5760320 585 }
kenjiArai 0:5b88d5760320 586
kenjiArai 0:5b88d5760320 587 socket->connected = (ret == NSAPI_ERROR_OK) ? true : false;
kenjiArai 0:5b88d5760320 588
kenjiArai 0:5b88d5760320 589 return ret;
kenjiArai 0:5b88d5760320 590 }
kenjiArai 0:5b88d5760320 591
kenjiArai 0:5b88d5760320 592 int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
kenjiArai 0:5b88d5760320 593 {
kenjiArai 0:5b88d5760320 594 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 595 }
kenjiArai 0:5b88d5760320 596
kenjiArai 0:5b88d5760320 597 int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
kenjiArai 0:5b88d5760320 598 {
kenjiArai 0:5b88d5760320 599 nsapi_error_t status;
kenjiArai 0:5b88d5760320 600 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 601 uint8_t expect_false = false;
kenjiArai 0:5b88d5760320 602
kenjiArai 0:5b88d5760320 603 if (!socket) {
kenjiArai 0:5b88d5760320 604 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 605 }
kenjiArai 0:5b88d5760320 606
kenjiArai 0:5b88d5760320 607 if (!_sock_i[socket->id].open) {
kenjiArai 0:5b88d5760320 608 return NSAPI_ERROR_CONNECTION_LOST;
kenjiArai 0:5b88d5760320 609 }
kenjiArai 0:5b88d5760320 610
kenjiArai 0:5b88d5760320 611 if (!size) {
kenjiArai 0:5b88d5760320 612 // Firmware limitation
kenjiArai 0:5b88d5760320 613 return socket->proto == NSAPI_TCP ? 0 : NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 614 }
kenjiArai 0:5b88d5760320 615
kenjiArai 0:5b88d5760320 616 status = _esp.send(socket->id, data, size);
kenjiArai 0:5b88d5760320 617
kenjiArai 0:5b88d5760320 618 if (status == NSAPI_ERROR_WOULD_BLOCK
kenjiArai 0:5b88d5760320 619 && socket->proto == NSAPI_TCP
kenjiArai 0:5b88d5760320 620 && core_util_atomic_cas_u8(&_cbs[socket->id].deferred, &expect_false, true)) {
kenjiArai 0:5b88d5760320 621 tr_debug("Postponing SIGIO from the device");
kenjiArai 0:5b88d5760320 622 if (!_global_event_queue->call_in(50, callback(this, &ESP8266Interface::event_deferred))) {
kenjiArai 0:5b88d5760320 623 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
kenjiArai 0:5b88d5760320 624 "socket_send(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
kenjiArai 0:5b88d5760320 625 }
kenjiArai 0:5b88d5760320 626
kenjiArai 0:5b88d5760320 627 } else if (status == NSAPI_ERROR_WOULD_BLOCK && socket->proto == NSAPI_UDP) {
kenjiArai 0:5b88d5760320 628 status = NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 629 }
kenjiArai 0:5b88d5760320 630
kenjiArai 0:5b88d5760320 631 return status != NSAPI_ERROR_OK ? status : size;
kenjiArai 0:5b88d5760320 632 }
kenjiArai 0:5b88d5760320 633
kenjiArai 0:5b88d5760320 634 int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
kenjiArai 0:5b88d5760320 635 {
kenjiArai 0:5b88d5760320 636 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 637
kenjiArai 0:5b88d5760320 638 if (!socket) {
kenjiArai 0:5b88d5760320 639 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 640 }
kenjiArai 0:5b88d5760320 641
kenjiArai 0:5b88d5760320 642 if (!_sock_i[socket->id].open) {
kenjiArai 0:5b88d5760320 643 return NSAPI_ERROR_CONNECTION_LOST;
kenjiArai 0:5b88d5760320 644 }
kenjiArai 0:5b88d5760320 645
kenjiArai 0:5b88d5760320 646 int32_t recv;
kenjiArai 0:5b88d5760320 647 if (socket->proto == NSAPI_TCP) {
kenjiArai 0:5b88d5760320 648 recv = _esp.recv_tcp(socket->id, data, size);
kenjiArai 0:5b88d5760320 649 if (recv <= 0 && recv != NSAPI_ERROR_WOULD_BLOCK) {
kenjiArai 0:5b88d5760320 650 socket->connected = false;
kenjiArai 0:5b88d5760320 651 }
kenjiArai 0:5b88d5760320 652 } else {
kenjiArai 0:5b88d5760320 653 recv = _esp.recv_udp(socket->id, data, size);
kenjiArai 0:5b88d5760320 654 }
kenjiArai 0:5b88d5760320 655
kenjiArai 0:5b88d5760320 656 return recv;
kenjiArai 0:5b88d5760320 657 }
kenjiArai 0:5b88d5760320 658
kenjiArai 0:5b88d5760320 659 int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
kenjiArai 0:5b88d5760320 660 {
kenjiArai 0:5b88d5760320 661 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 662
kenjiArai 0:5b88d5760320 663 if (!socket) {
kenjiArai 0:5b88d5760320 664 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 665 }
kenjiArai 0:5b88d5760320 666
kenjiArai 0:5b88d5760320 667 if ((strcmp(addr.get_ip_address(), "0.0.0.0") == 0) || !addr.get_port()) {
kenjiArai 0:5b88d5760320 668 return NSAPI_ERROR_DNS_FAILURE;
kenjiArai 0:5b88d5760320 669 }
kenjiArai 0:5b88d5760320 670
kenjiArai 0:5b88d5760320 671 if (socket->connected && socket->addr != addr) {
kenjiArai 0:5b88d5760320 672 if (!_esp.close(socket->id)) {
kenjiArai 0:5b88d5760320 673 return NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 674 }
kenjiArai 0:5b88d5760320 675 socket->connected = false;
kenjiArai 0:5b88d5760320 676 }
kenjiArai 0:5b88d5760320 677
kenjiArai 0:5b88d5760320 678 if (!socket->connected) {
kenjiArai 0:5b88d5760320 679 int err = socket_connect(socket, addr);
kenjiArai 0:5b88d5760320 680 if (err < 0) {
kenjiArai 0:5b88d5760320 681 return err;
kenjiArai 0:5b88d5760320 682 }
kenjiArai 0:5b88d5760320 683 socket->addr = addr;
kenjiArai 0:5b88d5760320 684 }
kenjiArai 0:5b88d5760320 685
kenjiArai 0:5b88d5760320 686 return socket_send(socket, data, size);
kenjiArai 0:5b88d5760320 687 }
kenjiArai 0:5b88d5760320 688
kenjiArai 0:5b88d5760320 689 int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
kenjiArai 0:5b88d5760320 690 {
kenjiArai 0:5b88d5760320 691 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 692
kenjiArai 0:5b88d5760320 693 if (!socket) {
kenjiArai 0:5b88d5760320 694 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 695 }
kenjiArai 0:5b88d5760320 696
kenjiArai 0:5b88d5760320 697 int ret = socket_recv(socket, data, size);
kenjiArai 0:5b88d5760320 698 if (ret >= 0 && addr) {
kenjiArai 0:5b88d5760320 699 *addr = socket->addr;
kenjiArai 0:5b88d5760320 700 }
kenjiArai 0:5b88d5760320 701
kenjiArai 0:5b88d5760320 702 return ret;
kenjiArai 0:5b88d5760320 703 }
kenjiArai 0:5b88d5760320 704
kenjiArai 0:5b88d5760320 705 void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
kenjiArai 0:5b88d5760320 706 {
kenjiArai 0:5b88d5760320 707 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 708 _cbs[socket->id].callback = callback;
kenjiArai 0:5b88d5760320 709 _cbs[socket->id].data = data;
kenjiArai 0:5b88d5760320 710 }
kenjiArai 0:5b88d5760320 711
kenjiArai 0:5b88d5760320 712 nsapi_error_t ESP8266Interface::setsockopt(nsapi_socket_t handle, int level,
kenjiArai 0:5b88d5760320 713 int optname, const void *optval, unsigned optlen)
kenjiArai 0:5b88d5760320 714 {
kenjiArai 0:5b88d5760320 715 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 716
kenjiArai 0:5b88d5760320 717 if (!optlen) {
kenjiArai 0:5b88d5760320 718 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 719 } else if (!socket) {
kenjiArai 0:5b88d5760320 720 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 721 }
kenjiArai 0:5b88d5760320 722
kenjiArai 0:5b88d5760320 723 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
kenjiArai 0:5b88d5760320 724 switch (optname) {
kenjiArai 0:5b88d5760320 725 case NSAPI_KEEPALIVE: {
kenjiArai 0:5b88d5760320 726 if (socket->connected) { // ESP8266 limitation, keepalive needs to be given before connecting
kenjiArai 0:5b88d5760320 727 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 728 }
kenjiArai 0:5b88d5760320 729
kenjiArai 0:5b88d5760320 730 if (optlen == sizeof(int)) {
kenjiArai 0:5b88d5760320 731 int secs = *(int *)optval;
kenjiArai 0:5b88d5760320 732 if (secs >= 0 && secs <= 7200) {
kenjiArai 0:5b88d5760320 733 socket->keepalive = secs;
kenjiArai 0:5b88d5760320 734 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 735 }
kenjiArai 0:5b88d5760320 736 }
kenjiArai 0:5b88d5760320 737 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 738 }
kenjiArai 0:5b88d5760320 739 }
kenjiArai 0:5b88d5760320 740 }
kenjiArai 0:5b88d5760320 741
kenjiArai 0:5b88d5760320 742 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 743 }
kenjiArai 0:5b88d5760320 744
kenjiArai 0:5b88d5760320 745 nsapi_error_t ESP8266Interface::getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen)
kenjiArai 0:5b88d5760320 746 {
kenjiArai 0:5b88d5760320 747 struct esp8266_socket *socket = (struct esp8266_socket *)handle;
kenjiArai 0:5b88d5760320 748
kenjiArai 0:5b88d5760320 749 if (!optval || !optlen) {
kenjiArai 0:5b88d5760320 750 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 751 } else if (!socket) {
kenjiArai 0:5b88d5760320 752 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 753 }
kenjiArai 0:5b88d5760320 754
kenjiArai 0:5b88d5760320 755 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
kenjiArai 0:5b88d5760320 756 switch (optname) {
kenjiArai 0:5b88d5760320 757 case NSAPI_KEEPALIVE: {
kenjiArai 0:5b88d5760320 758 if (*optlen > sizeof(int)) {
kenjiArai 0:5b88d5760320 759 *optlen = sizeof(int);
kenjiArai 0:5b88d5760320 760 }
kenjiArai 0:5b88d5760320 761 memcpy(optval, &(socket->keepalive), *optlen);
kenjiArai 0:5b88d5760320 762 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 763 }
kenjiArai 0:5b88d5760320 764 }
kenjiArai 0:5b88d5760320 765 }
kenjiArai 0:5b88d5760320 766
kenjiArai 0:5b88d5760320 767 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 768 }
kenjiArai 0:5b88d5760320 769
kenjiArai 0:5b88d5760320 770
kenjiArai 0:5b88d5760320 771 void ESP8266Interface::event()
kenjiArai 0:5b88d5760320 772 {
kenjiArai 0:5b88d5760320 773 if (!_oob_event_id) {
kenjiArai 0:5b88d5760320 774 // Throttles event creation by using arbitrary small delay
kenjiArai 0:5b88d5760320 775 _oob_event_id = _global_event_queue->call_in(50, callback(this, &ESP8266Interface::proc_oob_evnt));
kenjiArai 0:5b88d5760320 776 if (!_oob_event_id) {
kenjiArai 0:5b88d5760320 777 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
kenjiArai 0:5b88d5760320 778 "ESP8266Interface::event(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
kenjiArai 0:5b88d5760320 779 }
kenjiArai 0:5b88d5760320 780 }
kenjiArai 0:5b88d5760320 781
kenjiArai 0:5b88d5760320 782 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
kenjiArai 0:5b88d5760320 783 if (_cbs[i].callback) {
kenjiArai 0:5b88d5760320 784 _cbs[i].callback(_cbs[i].data);
kenjiArai 0:5b88d5760320 785 }
kenjiArai 0:5b88d5760320 786 }
kenjiArai 0:5b88d5760320 787 }
kenjiArai 0:5b88d5760320 788
kenjiArai 0:5b88d5760320 789 void ESP8266Interface::event_deferred()
kenjiArai 0:5b88d5760320 790 {
kenjiArai 0:5b88d5760320 791 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
kenjiArai 0:5b88d5760320 792 uint8_t expect_true = true;
kenjiArai 0:5b88d5760320 793 if (core_util_atomic_cas_u8(&_cbs[i].deferred, &expect_true, false) && _cbs[i].callback) {
kenjiArai 0:5b88d5760320 794 _cbs[i].callback(_cbs[i].data);
kenjiArai 0:5b88d5760320 795 }
kenjiArai 0:5b88d5760320 796 }
kenjiArai 0:5b88d5760320 797 }
kenjiArai 0:5b88d5760320 798
kenjiArai 0:5b88d5760320 799 void ESP8266Interface::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
kenjiArai 0:5b88d5760320 800 {
kenjiArai 0:5b88d5760320 801 _conn_stat_cb = status_cb;
kenjiArai 0:5b88d5760320 802 }
kenjiArai 0:5b88d5760320 803
kenjiArai 0:5b88d5760320 804 nsapi_connection_status_t ESP8266Interface::get_connection_status() const
kenjiArai 0:5b88d5760320 805 {
kenjiArai 0:5b88d5760320 806 return _conn_stat;
kenjiArai 0:5b88d5760320 807 }
kenjiArai 0:5b88d5760320 808
kenjiArai 0:5b88d5760320 809 #if MBED_CONF_ESP8266_PROVIDE_DEFAULT
kenjiArai 0:5b88d5760320 810
kenjiArai 0:5b88d5760320 811 WiFiInterface *WiFiInterface::get_default_instance()
kenjiArai 0:5b88d5760320 812 {
kenjiArai 0:5b88d5760320 813 static ESP8266Interface esp;
kenjiArai 0:5b88d5760320 814 return &esp;
kenjiArai 0:5b88d5760320 815 }
kenjiArai 0:5b88d5760320 816
kenjiArai 0:5b88d5760320 817 #endif
kenjiArai 0:5b88d5760320 818
kenjiArai 0:5b88d5760320 819 void ESP8266Interface::refresh_conn_state_cb()
kenjiArai 0:5b88d5760320 820 {
kenjiArai 0:5b88d5760320 821 nsapi_connection_status_t prev_stat = _conn_stat;
kenjiArai 0:5b88d5760320 822 _conn_stat = _esp.connection_status();
kenjiArai 0:5b88d5760320 823
kenjiArai 0:5b88d5760320 824 switch (_conn_stat) {
kenjiArai 0:5b88d5760320 825 // Doesn't require changes
kenjiArai 0:5b88d5760320 826 case NSAPI_STATUS_CONNECTING:
kenjiArai 0:5b88d5760320 827 case NSAPI_STATUS_GLOBAL_UP:
kenjiArai 0:5b88d5760320 828 break;
kenjiArai 0:5b88d5760320 829 // Start from scratch if connection drops/is dropped
kenjiArai 0:5b88d5760320 830 case NSAPI_STATUS_DISCONNECTED:
kenjiArai 0:5b88d5760320 831 break;
kenjiArai 0:5b88d5760320 832 // Handled on AT layer
kenjiArai 0:5b88d5760320 833 case NSAPI_STATUS_LOCAL_UP:
kenjiArai 0:5b88d5760320 834 case NSAPI_STATUS_ERROR_UNSUPPORTED:
kenjiArai 0:5b88d5760320 835 default:
kenjiArai 0:5b88d5760320 836 _initialized = false;
kenjiArai 0:5b88d5760320 837 _conn_stat = NSAPI_STATUS_DISCONNECTED;
kenjiArai 0:5b88d5760320 838 for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
kenjiArai 0:5b88d5760320 839 _sock_i[i].open = false;
kenjiArai 0:5b88d5760320 840 _sock_i[i].sport = 0;
kenjiArai 0:5b88d5760320 841 }
kenjiArai 0:5b88d5760320 842 }
kenjiArai 0:5b88d5760320 843
kenjiArai 0:5b88d5760320 844 if (prev_stat == _conn_stat) {
kenjiArai 0:5b88d5760320 845 return;
kenjiArai 0:5b88d5760320 846 }
kenjiArai 0:5b88d5760320 847
kenjiArai 0:5b88d5760320 848 tr_debug("refresh_conn_state_cb(): changed to %d", _conn_stat);
kenjiArai 0:5b88d5760320 849
kenjiArai 0:5b88d5760320 850 // Inform upper layers
kenjiArai 0:5b88d5760320 851 if (_conn_stat_cb) {
kenjiArai 0:5b88d5760320 852 _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
kenjiArai 0:5b88d5760320 853 }
kenjiArai 0:5b88d5760320 854 }
kenjiArai 0:5b88d5760320 855
kenjiArai 0:5b88d5760320 856 void ESP8266Interface::proc_oob_evnt()
kenjiArai 0:5b88d5760320 857 {
kenjiArai 0:5b88d5760320 858 _oob_event_id = 0; // Allows creation of a new event
kenjiArai 0:5b88d5760320 859 _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
kenjiArai 0:5b88d5760320 860 }
kenjiArai 0:5b88d5760320 861
kenjiArai 0:5b88d5760320 862 nsapi_error_t ESP8266Interface::_conn_status_to_error()
kenjiArai 0:5b88d5760320 863 {
kenjiArai 0:5b88d5760320 864 nsapi_error_t ret;
kenjiArai 0:5b88d5760320 865
kenjiArai 0:5b88d5760320 866 _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
kenjiArai 0:5b88d5760320 867
kenjiArai 0:5b88d5760320 868 switch (_conn_stat) {
kenjiArai 0:5b88d5760320 869 case NSAPI_STATUS_DISCONNECTED:
kenjiArai 0:5b88d5760320 870 ret = NSAPI_ERROR_NO_CONNECTION;
kenjiArai 0:5b88d5760320 871 break;
kenjiArai 0:5b88d5760320 872 case NSAPI_STATUS_CONNECTING:
kenjiArai 0:5b88d5760320 873 ret = NSAPI_ERROR_ALREADY;
kenjiArai 0:5b88d5760320 874 break;
kenjiArai 0:5b88d5760320 875 case NSAPI_STATUS_GLOBAL_UP:
kenjiArai 0:5b88d5760320 876 ret = NSAPI_ERROR_IS_CONNECTED;
kenjiArai 0:5b88d5760320 877 break;
kenjiArai 0:5b88d5760320 878 default:
kenjiArai 0:5b88d5760320 879 ret = NSAPI_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 880 }
kenjiArai 0:5b88d5760320 881
kenjiArai 0:5b88d5760320 882 return ret;
kenjiArai 0:5b88d5760320 883 }
kenjiArai 0:5b88d5760320 884
kenjiArai 0:5b88d5760320 885 nsapi_error_t ESP8266Interface::set_blocking(bool blocking)
kenjiArai 0:5b88d5760320 886 {
kenjiArai 0:5b88d5760320 887 _if_blocking = blocking;
kenjiArai 0:5b88d5760320 888
kenjiArai 0:5b88d5760320 889 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 890 }
kenjiArai 0:5b88d5760320 891
kenjiArai 0:5b88d5760320 892 nsapi_error_t ESP8266Interface::set_country_code(bool track_ap, const char *country_code, int len, int channel_start, int channels)
kenjiArai 0:5b88d5760320 893 {
kenjiArai 0:5b88d5760320 894 for (int i = 0; i < len; i++) {
kenjiArai 0:5b88d5760320 895 // Validation done by firmware
kenjiArai 0:5b88d5760320 896 if (!country_code[i]) {
kenjiArai 0:5b88d5760320 897 tr_warning("invalid country code");
kenjiArai 0:5b88d5760320 898 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 899 }
kenjiArai 0:5b88d5760320 900 }
kenjiArai 0:5b88d5760320 901
kenjiArai 0:5b88d5760320 902 _ch_info.track_ap = track_ap;
kenjiArai 0:5b88d5760320 903
kenjiArai 0:5b88d5760320 904 // Firmware takes only first three characters
kenjiArai 0:5b88d5760320 905 strncpy(_ch_info.country_code, country_code, sizeof(_ch_info.country_code));
kenjiArai 0:5b88d5760320 906 _ch_info.country_code[sizeof(_ch_info.country_code) - 1] = '\0';
kenjiArai 0:5b88d5760320 907
kenjiArai 0:5b88d5760320 908 _ch_info.channel_start = channel_start;
kenjiArai 0:5b88d5760320 909 _ch_info.channels = channels;
kenjiArai 0:5b88d5760320 910
kenjiArai 0:5b88d5760320 911 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 912 }
kenjiArai 0:5b88d5760320 913
kenjiArai 0:5b88d5760320 914 #endif