The driver for the ESP32 WiFi module

The ESP32 WiFi driver for Mbed OS

The Mbed OS driver for the ESP32 WiFi module.

Firmware version

How to write mbed-os compatible firmware : https://github.com/d-kato/GR-Boards_ESP32_Serial_Bridge

Restrictions

  • Setting up an UDP server is not possible
  • The serial port does not have hardware flow control enabled. The AT command set does not either have a way to limit the download rate. Therefore, downloading anything larger than the serial port input buffer is unreliable. An application should be able to read fast enough to stay ahead of the network. This affects mostly the TCP protocol where data would be lost with no notification. On UDP, this would lead to only packet losses which the higher layer protocol should recover from.

Committer:
dkato
Date:
Fri Jun 29 06:17:38 2018 +0000
Revision:
0:92d12d355ba9
Child:
1:5d78eedef723
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:92d12d355ba9 1 /* ESP32 implementation of NetworkInterfaceAPI
dkato 0:92d12d355ba9 2 * Copyright (c) 2015 ARM Limited
dkato 0:92d12d355ba9 3 * Copyright (c) 2017 Renesas Electronics Corporation
dkato 0:92d12d355ba9 4 *
dkato 0:92d12d355ba9 5 * Licensed under the Apache License, Version 2.0 (the "License");
dkato 0:92d12d355ba9 6 * you may not use this file except in compliance with the License.
dkato 0:92d12d355ba9 7 * You may obtain a copy of the License at
dkato 0:92d12d355ba9 8 *
dkato 0:92d12d355ba9 9 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:92d12d355ba9 10 *
dkato 0:92d12d355ba9 11 * Unless required by applicable law or agreed to in writing, software
dkato 0:92d12d355ba9 12 * distributed under the License is distributed on an "AS IS" BASIS,
dkato 0:92d12d355ba9 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:92d12d355ba9 14 * See the License for the specific language governing permissions and
dkato 0:92d12d355ba9 15 * limitations under the License.
dkato 0:92d12d355ba9 16 */
dkato 0:92d12d355ba9 17
dkato 0:92d12d355ba9 18 #include <string.h>
dkato 0:92d12d355ba9 19 #include "ESP32Stack.h"
dkato 0:92d12d355ba9 20
dkato 0:92d12d355ba9 21 // ESP32Stack implementation
dkato 0:92d12d355ba9 22 ESP32Stack::ESP32Stack(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate)
dkato 0:92d12d355ba9 23 {
dkato 0:92d12d355ba9 24 _esp = ESP32::getESP32Inst(en, io0, tx, rx, debug, baudrate);
dkato 0:92d12d355ba9 25 memset(_local_ports, 0, sizeof(_local_ports));
dkato 0:92d12d355ba9 26 }
dkato 0:92d12d355ba9 27
dkato 0:92d12d355ba9 28 struct esp32_socket {
dkato 0:92d12d355ba9 29 int id;
dkato 0:92d12d355ba9 30 nsapi_protocol_t proto;
dkato 0:92d12d355ba9 31 bool connected;
dkato 0:92d12d355ba9 32 SocketAddress addr;
dkato 0:92d12d355ba9 33 int keepalive; // TCP
dkato 0:92d12d355ba9 34 bool accept_id;
dkato 0:92d12d355ba9 35 bool tcp_server;
dkato 0:92d12d355ba9 36 };
dkato 0:92d12d355ba9 37
dkato 0:92d12d355ba9 38 int ESP32Stack::socket_open(void **handle, nsapi_protocol_t proto)
dkato 0:92d12d355ba9 39 {
dkato 0:92d12d355ba9 40 // Look for an unused socket
dkato 0:92d12d355ba9 41 int id = _esp->get_free_id();
dkato 0:92d12d355ba9 42
dkato 0:92d12d355ba9 43 if (id == -1) {
dkato 0:92d12d355ba9 44 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 45 }
dkato 0:92d12d355ba9 46
dkato 0:92d12d355ba9 47 struct esp32_socket *socket = new struct esp32_socket;
dkato 0:92d12d355ba9 48 if (!socket) {
dkato 0:92d12d355ba9 49 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 50 }
dkato 0:92d12d355ba9 51
dkato 0:92d12d355ba9 52 socket->id = id;
dkato 0:92d12d355ba9 53 socket->proto = proto;
dkato 0:92d12d355ba9 54 socket->connected = false;
dkato 0:92d12d355ba9 55 socket->keepalive = 0;
dkato 0:92d12d355ba9 56 socket->accept_id = false;
dkato 0:92d12d355ba9 57 socket->tcp_server = false;
dkato 0:92d12d355ba9 58 *handle = socket;
dkato 0:92d12d355ba9 59 return 0;
dkato 0:92d12d355ba9 60 }
dkato 0:92d12d355ba9 61
dkato 0:92d12d355ba9 62 int ESP32Stack::socket_close(void *handle)
dkato 0:92d12d355ba9 63 {
dkato 0:92d12d355ba9 64 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 65 int err = 0;
dkato 0:92d12d355ba9 66
dkato 0:92d12d355ba9 67 if (!socket) {
dkato 0:92d12d355ba9 68 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 69 }
dkato 0:92d12d355ba9 70
dkato 0:92d12d355ba9 71 if (!_esp->close(socket->id, socket->accept_id)) {
dkato 0:92d12d355ba9 72 err = NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 73 }
dkato 0:92d12d355ba9 74
dkato 0:92d12d355ba9 75 if (socket->tcp_server) {
dkato 0:92d12d355ba9 76 _esp->del_server();
dkato 0:92d12d355ba9 77 }
dkato 0:92d12d355ba9 78 _local_ports[socket->id] = 0;
dkato 0:92d12d355ba9 79
dkato 0:92d12d355ba9 80 delete socket;
dkato 0:92d12d355ba9 81 return err;
dkato 0:92d12d355ba9 82 }
dkato 0:92d12d355ba9 83
dkato 0:92d12d355ba9 84 int ESP32Stack::socket_bind(void *handle, const SocketAddress &address)
dkato 0:92d12d355ba9 85 {
dkato 0:92d12d355ba9 86 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 87
dkato 0:92d12d355ba9 88 if (!socket) {
dkato 0:92d12d355ba9 89 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 90 }
dkato 0:92d12d355ba9 91
dkato 0:92d12d355ba9 92 if (socket->proto == NSAPI_UDP) {
dkato 0:92d12d355ba9 93 if(address.get_addr().version != NSAPI_UNSPEC) {
dkato 0:92d12d355ba9 94 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 95 }
dkato 0:92d12d355ba9 96
dkato 0:92d12d355ba9 97 for(int id = 0; id < ESP32::SOCKET_COUNT; id++) {
dkato 0:92d12d355ba9 98 if(_local_ports[id] == address.get_port() && id != socket->id) { // Port already reserved by another socket
dkato 0:92d12d355ba9 99 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 100 } else if (id == socket->id && socket->connected) {
dkato 0:92d12d355ba9 101 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 102 }
dkato 0:92d12d355ba9 103 }
dkato 0:92d12d355ba9 104 _local_ports[socket->id] = address.get_port();
dkato 0:92d12d355ba9 105 return 0;
dkato 0:92d12d355ba9 106 }
dkato 0:92d12d355ba9 107
dkato 0:92d12d355ba9 108 socket->addr = address;
dkato 0:92d12d355ba9 109 return 0;
dkato 0:92d12d355ba9 110 }
dkato 0:92d12d355ba9 111
dkato 0:92d12d355ba9 112 int ESP32Stack::socket_listen(void *handle, int backlog)
dkato 0:92d12d355ba9 113 {
dkato 0:92d12d355ba9 114 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 115
dkato 0:92d12d355ba9 116 (void)backlog;
dkato 0:92d12d355ba9 117
dkato 0:92d12d355ba9 118 if (!socket) {
dkato 0:92d12d355ba9 119 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 120 }
dkato 0:92d12d355ba9 121
dkato 0:92d12d355ba9 122 if (socket->proto != NSAPI_TCP) {
dkato 0:92d12d355ba9 123 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 124 }
dkato 0:92d12d355ba9 125
dkato 0:92d12d355ba9 126 if (!_esp->cre_server(socket->addr.get_port())) {
dkato 0:92d12d355ba9 127 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 128 }
dkato 0:92d12d355ba9 129
dkato 0:92d12d355ba9 130 socket->tcp_server = true;
dkato 0:92d12d355ba9 131 return 0;
dkato 0:92d12d355ba9 132 }
dkato 0:92d12d355ba9 133
dkato 0:92d12d355ba9 134 int ESP32Stack::socket_connect(void *handle, const SocketAddress &addr)
dkato 0:92d12d355ba9 135 {
dkato 0:92d12d355ba9 136 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 137
dkato 0:92d12d355ba9 138 if (!socket) {
dkato 0:92d12d355ba9 139 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 140 }
dkato 0:92d12d355ba9 141
dkato 0:92d12d355ba9 142 if (socket->proto == NSAPI_UDP) {
dkato 0:92d12d355ba9 143 if (!_esp->open("UDP", socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id])) {
dkato 0:92d12d355ba9 144 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 145 }
dkato 0:92d12d355ba9 146 } else {
dkato 0:92d12d355ba9 147 if (!_esp->open("TCP", socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) {
dkato 0:92d12d355ba9 148 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 149 }
dkato 0:92d12d355ba9 150 }
dkato 0:92d12d355ba9 151
dkato 0:92d12d355ba9 152 socket->connected = true;
dkato 0:92d12d355ba9 153 return 0;
dkato 0:92d12d355ba9 154 }
dkato 0:92d12d355ba9 155
dkato 0:92d12d355ba9 156 int ESP32Stack::socket_accept(void *server, void **socket, SocketAddress *addr)
dkato 0:92d12d355ba9 157 {
dkato 0:92d12d355ba9 158 struct esp32_socket *socket_new = new struct esp32_socket;
dkato 0:92d12d355ba9 159 int id;
dkato 0:92d12d355ba9 160
dkato 0:92d12d355ba9 161 if (!socket_new) {
dkato 0:92d12d355ba9 162 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 163 }
dkato 0:92d12d355ba9 164
dkato 0:92d12d355ba9 165 if (!_esp->accept(&id)) {
dkato 0:92d12d355ba9 166 delete socket_new;
dkato 0:92d12d355ba9 167 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 168 }
dkato 0:92d12d355ba9 169
dkato 0:92d12d355ba9 170 socket_new->id = id;
dkato 0:92d12d355ba9 171 socket_new->proto = NSAPI_TCP;
dkato 0:92d12d355ba9 172 socket_new->connected = true;
dkato 0:92d12d355ba9 173 socket_new->accept_id = true;
dkato 0:92d12d355ba9 174 socket_new->tcp_server = false;
dkato 0:92d12d355ba9 175 *socket = socket_new;
dkato 0:92d12d355ba9 176
dkato 0:92d12d355ba9 177 return 0;
dkato 0:92d12d355ba9 178 }
dkato 0:92d12d355ba9 179
dkato 0:92d12d355ba9 180 int ESP32Stack::socket_send(void *handle, const void *data, unsigned size)
dkato 0:92d12d355ba9 181 {
dkato 0:92d12d355ba9 182 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 183
dkato 0:92d12d355ba9 184 if (!socket) {
dkato 0:92d12d355ba9 185 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 186 }
dkato 0:92d12d355ba9 187
dkato 0:92d12d355ba9 188 if (!_esp->send(socket->id, data, size)) {
dkato 0:92d12d355ba9 189 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 190 }
dkato 0:92d12d355ba9 191
dkato 0:92d12d355ba9 192 return size;
dkato 0:92d12d355ba9 193 }
dkato 0:92d12d355ba9 194
dkato 0:92d12d355ba9 195 int ESP32Stack::socket_recv(void *handle, void *data, unsigned size)
dkato 0:92d12d355ba9 196 {
dkato 0:92d12d355ba9 197 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 198
dkato 0:92d12d355ba9 199 if (!socket) {
dkato 0:92d12d355ba9 200 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 201 }
dkato 0:92d12d355ba9 202
dkato 0:92d12d355ba9 203 int32_t recv = _esp->recv(socket->id, data, size);
dkato 0:92d12d355ba9 204 if (recv == -1) {
dkato 0:92d12d355ba9 205 return NSAPI_ERROR_WOULD_BLOCK;
dkato 0:92d12d355ba9 206 } else if (recv < 0) {
dkato 0:92d12d355ba9 207 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 208 } else {
dkato 0:92d12d355ba9 209 // do nothing
dkato 0:92d12d355ba9 210 }
dkato 0:92d12d355ba9 211
dkato 0:92d12d355ba9 212 return recv;
dkato 0:92d12d355ba9 213 }
dkato 0:92d12d355ba9 214
dkato 0:92d12d355ba9 215 int ESP32Stack::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
dkato 0:92d12d355ba9 216 {
dkato 0:92d12d355ba9 217 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 218
dkato 0:92d12d355ba9 219 if (!socket) {
dkato 0:92d12d355ba9 220 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 221 }
dkato 0:92d12d355ba9 222
dkato 0:92d12d355ba9 223 if (socket->connected && socket->addr != addr) {
dkato 0:92d12d355ba9 224 if (!_esp->close(socket->id, socket->accept_id)) {
dkato 0:92d12d355ba9 225 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 226 }
dkato 0:92d12d355ba9 227 socket->connected = false;
dkato 0:92d12d355ba9 228 }
dkato 0:92d12d355ba9 229
dkato 0:92d12d355ba9 230 if (!socket->connected) {
dkato 0:92d12d355ba9 231 int err = socket_connect(socket, addr);
dkato 0:92d12d355ba9 232 if (err < 0) {
dkato 0:92d12d355ba9 233 return err;
dkato 0:92d12d355ba9 234 }
dkato 0:92d12d355ba9 235 socket->addr = addr;
dkato 0:92d12d355ba9 236 }
dkato 0:92d12d355ba9 237
dkato 0:92d12d355ba9 238 return socket_send(socket, data, size);
dkato 0:92d12d355ba9 239 }
dkato 0:92d12d355ba9 240
dkato 0:92d12d355ba9 241 int ESP32Stack::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
dkato 0:92d12d355ba9 242 {
dkato 0:92d12d355ba9 243 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 244
dkato 0:92d12d355ba9 245 if (!socket) {
dkato 0:92d12d355ba9 246 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 247 }
dkato 0:92d12d355ba9 248
dkato 0:92d12d355ba9 249 int ret = socket_recv(socket, data, size);
dkato 0:92d12d355ba9 250 if (ret >= 0 && addr) {
dkato 0:92d12d355ba9 251 *addr = socket->addr;
dkato 0:92d12d355ba9 252 }
dkato 0:92d12d355ba9 253
dkato 0:92d12d355ba9 254 return ret;
dkato 0:92d12d355ba9 255 }
dkato 0:92d12d355ba9 256
dkato 0:92d12d355ba9 257 void ESP32Stack::socket_attach(void *handle, void (*callback)(void *), void *data)
dkato 0:92d12d355ba9 258 {
dkato 0:92d12d355ba9 259 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 260
dkato 0:92d12d355ba9 261 if (!socket) {
dkato 0:92d12d355ba9 262 return;
dkato 0:92d12d355ba9 263 }
dkato 0:92d12d355ba9 264
dkato 0:92d12d355ba9 265 _esp->socket_attach(socket->id, callback, data);
dkato 0:92d12d355ba9 266 }
dkato 0:92d12d355ba9 267
dkato 0:92d12d355ba9 268 nsapi_error_t ESP32Stack::setsockopt(nsapi_socket_t handle, int level,
dkato 0:92d12d355ba9 269 int optname, const void *optval, unsigned optlen)
dkato 0:92d12d355ba9 270 {
dkato 0:92d12d355ba9 271 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 272
dkato 0:92d12d355ba9 273 if (!optlen) {
dkato 0:92d12d355ba9 274 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 275 } else if (!socket) {
dkato 0:92d12d355ba9 276 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 277 }
dkato 0:92d12d355ba9 278
dkato 0:92d12d355ba9 279 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
dkato 0:92d12d355ba9 280 switch (optname) {
dkato 0:92d12d355ba9 281 case NSAPI_KEEPALIVE: {
dkato 0:92d12d355ba9 282 if(socket->connected) {// ESP32 limitation, keepalive needs to be given before connecting
dkato 0:92d12d355ba9 283 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 284 }
dkato 0:92d12d355ba9 285
dkato 0:92d12d355ba9 286 if (optlen == sizeof(int)) {
dkato 0:92d12d355ba9 287 int secs = *(int *)optval;
dkato 0:92d12d355ba9 288 if (secs >= 0 && secs <= 7200) {
dkato 0:92d12d355ba9 289 socket->keepalive = secs;
dkato 0:92d12d355ba9 290 return NSAPI_ERROR_OK;
dkato 0:92d12d355ba9 291 }
dkato 0:92d12d355ba9 292 }
dkato 0:92d12d355ba9 293 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 294 }
dkato 0:92d12d355ba9 295 }
dkato 0:92d12d355ba9 296 }
dkato 0:92d12d355ba9 297
dkato 0:92d12d355ba9 298 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 299 }
dkato 0:92d12d355ba9 300
dkato 0:92d12d355ba9 301 nsapi_error_t ESP32Stack::getsockopt(nsapi_socket_t handle, int level,
dkato 0:92d12d355ba9 302 int optname, void *optval, unsigned *optlen)
dkato 0:92d12d355ba9 303 {
dkato 0:92d12d355ba9 304 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 305
dkato 0:92d12d355ba9 306 if (!optval || !optlen) {
dkato 0:92d12d355ba9 307 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 308 } else if (!socket) {
dkato 0:92d12d355ba9 309 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 310 }
dkato 0:92d12d355ba9 311
dkato 0:92d12d355ba9 312 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
dkato 0:92d12d355ba9 313 switch (optname) {
dkato 0:92d12d355ba9 314 case NSAPI_KEEPALIVE: {
dkato 0:92d12d355ba9 315 if(*optlen > sizeof(int)) {
dkato 0:92d12d355ba9 316 *optlen = sizeof(int);
dkato 0:92d12d355ba9 317 }
dkato 0:92d12d355ba9 318 memcpy(optval, &(socket->keepalive), *optlen);
dkato 0:92d12d355ba9 319 return NSAPI_ERROR_OK;
dkato 0:92d12d355ba9 320 }
dkato 0:92d12d355ba9 321 }
dkato 0:92d12d355ba9 322 }
dkato 0:92d12d355ba9 323
dkato 0:92d12d355ba9 324 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 325 }
dkato 0:92d12d355ba9 326