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.

Files at this revision

API Documentation at this revision

Comitter:
dkato
Date:
Fri Jun 29 06:17:38 2018 +0000
Child:
1:5d78eedef723
Commit message:
first commit

Changed in this revision

ESP32/ESP32.cpp Show annotated file Show diff for this revision Revisions of this file
ESP32/ESP32.h Show annotated file Show diff for this revision Revisions of this file
ESP32Interface.cpp Show annotated file Show diff for this revision Revisions of this file
ESP32Interface.h Show annotated file Show diff for this revision Revisions of this file
ESP32InterfaceAP.cpp Show annotated file Show diff for this revision Revisions of this file
ESP32InterfaceAP.h Show annotated file Show diff for this revision Revisions of this file
ESP32Stack.cpp Show annotated file Show diff for this revision Revisions of this file
ESP32Stack.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32/ESP32.cpp	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,890 @@
+/* ESP32 Example
+ * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ESP32.h"
+
+#define ESP32_DEFAULT_BAUD_RATE   115200
+
+ESP32 * ESP32::instESP32 = NULL;
+
+ESP32 * ESP32::getESP32Inst(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate)
+{
+    if (instESP32 == NULL) {
+        instESP32 = new ESP32(en, io0, tx, rx, debug, baudrate);
+    } else {
+        if (debug) {
+            instESP32->debugOn(debug);
+        }
+    }
+    return instESP32;
+}
+
+ESP32::ESP32(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate)
+    : _p_wifi_en(NULL), _p_wifi_io0(NULL), init_end(false)
+    , _serial(tx, rx, ESP32_DEFAULT_BAUD_RATE), _parser(&_serial, "\r\n", 512)
+    , _packets(0), _packets_end(&_packets)
+    , _id_bits(0), _id_bits_close(0), _server_act(false)
+    , _wifi_status(STATUS_DISCONNECTED)
+    , _wifi_status_cb(NULL)
+{
+    if ((int)en != NC) {
+        _p_wifi_en = new DigitalOut(en);
+    }
+    if ((int)io0 != NC) {
+        _p_wifi_io0 = new DigitalOut(io0);
+    }
+
+    _wifi_mode = WIFIMODE_STATION;
+    _baudrate = baudrate;
+    memset(_ids, 0, sizeof(_ids));
+    memset(_cbs, 0, sizeof(_cbs));
+
+    _serial.set_baud(ESP32_DEFAULT_BAUD_RATE);
+    debugOn(debug);
+
+    _parser.oob("+IPD", callback(this, &ESP32::_packet_handler));
+    _parser.oob("0,CONNECT", callback(this, &ESP32::_connect_handler_0));
+    _parser.oob("1,CONNECT", callback(this, &ESP32::_connect_handler_1));
+    _parser.oob("2,CONNECT", callback(this, &ESP32::_connect_handler_2));
+    _parser.oob("3,CONNECT", callback(this, &ESP32::_connect_handler_3));
+    _parser.oob("4,CONNECT", callback(this, &ESP32::_connect_handler_4));
+    _parser.oob("0,CLOSED", callback(this, &ESP32::_closed_handler_0));
+    _parser.oob("1,CLOSED", callback(this, &ESP32::_closed_handler_1));
+    _parser.oob("2,CLOSED", callback(this, &ESP32::_closed_handler_2));
+    _parser.oob("3,CLOSED", callback(this, &ESP32::_closed_handler_3));
+    _parser.oob("4,CLOSED", callback(this, &ESP32::_closed_handler_4));
+    _parser.oob("WIFI ", callback(this, &ESP32::_connection_status_handler));
+
+    _serial.sigio(Callback<void()>(this, &ESP32::event));
+}
+
+void ESP32::debugOn(bool debug)
+{
+    _parser.debug_on((debug) ? 1 : 0);
+}
+
+int ESP32::get_firmware_version()
+{
+    int version;
+
+    _smutex.lock();
+    bool done = _parser.send("AT+GMR")
+           && _parser.recv("SDK version:%d", &version)
+           && _parser.recv("OK");
+    _smutex.unlock();
+
+    if(done) {
+        return version;
+    } else { 
+        // Older firmware versions do not prefix the version with "SDK version: "
+        return -1;
+    }
+}
+
+bool ESP32::startup()
+{
+    if (init_end) {
+        return true;
+    }
+
+    if (_p_wifi_io0 != NULL) {
+        _p_wifi_io0->write(1);
+    }
+    if (_p_wifi_en != NULL) {
+        _p_wifi_en->write(0);
+        Thread::wait(10);
+        _p_wifi_en->write(1);
+        _parser.recv("ready");
+    } else {
+        setTimeout(100);
+        _parser.recv("ready");
+    }
+
+    reset();
+    bool success = _parser.send("AT+CWMODE=%d", _wifi_mode)
+                && _parser.recv("OK")
+                && _parser.send("AT+CIPMUX=1")
+                && _parser.recv("OK")
+                && _parser.send("AT+CWAUTOCONN=0")
+                && _parser.recv("OK")
+                && _parser.send("AT+CWQAP")
+                && _parser.recv("OK");
+    if (success) {
+        init_end = true;
+    }
+
+    return success;
+}
+
+bool ESP32::restart()
+{
+    bool success;
+
+    _smutex.lock();
+    if (!init_end) {
+        success = startup();
+    } else {
+        reset();
+        success = _parser.send("AT+CWMODE=%d", _wifi_mode)
+               && _parser.recv("OK")
+               && _parser.send("AT+CIPMUX=1")
+               && _parser.recv("OK");
+    }
+    _smutex.unlock();
+
+    return success;
+}
+
+bool ESP32::set_mode(int mode)
+{
+    //only 3 valid modes
+    if (mode < 1 || mode > 3) {
+        return false;
+    }
+    if (_wifi_mode != mode) {
+        _wifi_mode = mode;
+        return restart();
+    }
+    return true;
+}
+
+bool ESP32::cre_server(int port)
+{
+    if (_server_act) {
+        return false;
+    }
+    _smutex.lock();
+    startup();
+    if (!(_parser.send("AT+CIPSERVER=1,%d", port)
+        && _parser.recv("OK"))) {
+        _smutex.unlock();
+        return false;
+    }
+    _server_act = true;
+    _smutex.unlock();
+    return true;
+}
+
+bool ESP32::del_server()
+{
+    _smutex.lock();
+    startup();
+    if (!(_parser.send("AT+CIPSERVER=0")
+        && _parser.recv("OK"))) {
+        _smutex.unlock();
+        return false;
+    }
+    _server_act = false;
+    _smutex.unlock();
+    return true;
+}
+
+void ESP32::socket_handler(bool connect, int id)
+{
+    _smutex.lock();
+    startup();
+    _cbs[id].Notified = 0;
+    if (connect) {
+        _id_bits |= (1 << id);
+        if (_server_act) {
+            _accept_id.push_back(id);
+        }
+    } else {
+        _id_bits &= ~(1 << id);
+        _id_bits_close |= (1 << id);
+        if (_server_act) {
+            for (size_t i = 0; i < _accept_id.size(); i++) {
+                if (id == _accept_id[i]) {
+                    _accept_id.erase(_accept_id.begin() + i);
+                }
+            }
+        }
+    }
+    _smutex.unlock();
+}
+
+bool ESP32::accept(int * p_id)
+{
+    bool ret = false;
+
+    while (!ret) {
+        if (!_server_act) {
+            break;
+        }
+
+        _smutex.lock();
+        startup();
+        if (!_accept_id.empty()) {
+            ret = true;
+        } else {
+            _parser.process_oob(); // Poll for inbound packets
+            if (!_accept_id.empty()) {
+                ret = true;
+            }
+        }
+        if (ret) {
+            *p_id = _accept_id[0];
+            _accept_id.erase(_accept_id.begin());
+        }
+        _smutex.unlock();
+        if (!ret) {
+            Thread::wait(5);
+        }
+    }
+
+    if (ret) {
+        for (int i = 0; i < 50; i++) {
+            if ((_id_bits_close & (1 << *p_id)) == 0) {
+                break;
+            }
+            Thread::wait(10);
+        }
+    }
+
+    return ret;
+}
+
+bool ESP32::reset(void)
+{
+    for (int i = 0; i < 2; i++) {
+        if (_parser.send("AT+RST")
+            && _parser.recv("OK")) {
+            _serial.set_baud(ESP32_DEFAULT_BAUD_RATE);
+            _parser.recv("ready");
+
+            if (_parser.send("AT+UART_CUR=%d,8,1,0,%d", _baudrate, 0)
+                && _parser.recv("OK")) {
+                _serial.set_baud(_baudrate);
+            }
+
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ESP32::dhcp(bool enabled, int mode)
+{
+    //only 3 valid modes
+    if (mode < 0 || mode > 2) {
+        return false;
+    }
+
+    _smutex.lock();
+    startup();
+    bool done = _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    return done;
+}
+
+bool ESP32::connect(const char *ap, const char *passPhrase)
+{
+    bool ret;
+
+    _wifi_status = STATUS_DISCONNECTED;
+
+    _smutex.lock();
+    startup();
+
+    setTimeout(ESP32_CONNECT_TIMEOUT);
+    ret = _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
+       && _parser.recv("OK");
+    setTimeout();
+    _smutex.unlock();
+    return ret;
+}
+
+bool ESP32::config_soft_ap(const char *ap, const char *passPhrase, uint8_t chl, uint8_t ecn)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CWSAP=\"%s\",\"%s\",%hhu,%hhu", ap, passPhrase, chl, ecn)
+       && _parser.recv("OK");
+    _smutex.unlock();
+    return ret;
+}
+
+bool ESP32::get_ssid(char *ap)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CWJAP?")
+       && _parser.recv("+CWJAP:\"%33[^\"]\",", ap)
+       && _parser.recv("OK");
+    _smutex.unlock();
+    return ret;
+}
+
+bool ESP32::disconnect(void)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CWQAP") && _parser.recv("OK");
+    _smutex.unlock();
+    return ret;
+}
+
+const char *ESP32::getIPAddress(void)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIFSR")
+       && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
+       && _parser.recv("OK");
+    _smutex.unlock();
+    if (!ret) {
+        return 0;
+    }
+    return _ip_buffer;
+}
+
+const char *ESP32::getIPAddress_ap(void)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIFSR")
+       && _parser.recv("+CIFSR:APIP,\"%15[^\"]\"", _ip_buffer_ap)
+       && _parser.recv("OK");
+    _smutex.unlock();
+    if (!ret) {
+        return 0;
+    }
+    return _ip_buffer_ap;
+}
+
+const char *ESP32::getMACAddress(void)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIFSR")
+       && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+    return _mac_buffer;
+}
+
+const char *ESP32::getMACAddress_ap(void)
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIFSR")
+       && _parser.recv("+CIFSR:APMAC,\"%17[^\"]\"", _mac_buffer_ap)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+    return _mac_buffer_ap;
+}
+
+const char *ESP32::getGateway()
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIPSTA?")
+       && _parser.recv("+CIPSTA:gateway:\"%15[^\"]\"", _gateway_buffer)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+    return _gateway_buffer;
+}
+
+const char *ESP32::getGateway_ap()
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIPAP?")
+       && _parser.recv("+CIPAP:gateway:\"%15[^\"]\"", _gateway_buffer_ap)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+    return _gateway_buffer_ap;
+}
+
+const char *ESP32::getNetmask()
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIPSTA?")
+       && _parser.recv("+CIPSTA:netmask:\"%15[^\"]\"", _netmask_buffer)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+    return _netmask_buffer;
+}
+
+const char *ESP32::getNetmask_ap()
+{
+    bool ret;
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CIPAP?")
+       && _parser.recv("+CIPAP:netmask:\"%15[^\"]\"", _netmask_buffer_ap)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+    return _netmask_buffer_ap;
+}
+
+int8_t ESP32::getRSSI()
+{
+    bool ret;
+    int8_t rssi;
+    char ssid[33];
+    char bssid[18];
+
+    _smutex.lock();
+    startup();
+    ret = _parser.send("AT+CWJAP?")
+       && _parser.recv("+CWJAP:\"%32[^\"]\",\"%17[^\"]\"", ssid, bssid)
+       && _parser.recv("OK");
+    if (!ret) {
+        _smutex.unlock();
+        return 0;
+    }
+
+    ret = _parser.send("AT+CWLAP=\"%s\",\"%s\"", ssid, bssid)
+       && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
+       && _parser.recv("OK");
+    _smutex.unlock();
+
+    if (!ret) {
+        return 0;
+    }
+
+    return rssi;
+}
+
+int ESP32::scan(WiFiAccessPoint *res, unsigned limit)
+{
+    unsigned cnt = 0;
+    nsapi_wifi_ap_t ap;
+
+    if (!init_end) {
+        _smutex.lock();
+        startup();
+        _smutex.unlock();
+        Thread::wait(1500);
+    }
+
+    _smutex.lock();
+    setTimeout(5000);
+    if (!_parser.send("AT+CWLAP")) {
+        _smutex.unlock();
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    while (recv_ap(&ap)) {
+        if (cnt < limit) {
+            res[cnt] = WiFiAccessPoint(ap);
+        }
+
+        cnt++;
+        if ((limit != 0) && (cnt >= limit)) {
+            break;
+        }
+        setTimeout(500);
+    }
+    setTimeout(10);
+    _parser.recv("OK");
+    setTimeout();
+    _smutex.unlock();
+
+    return cnt;
+}
+
+bool ESP32::isConnected(void)
+{
+    return getIPAddress() != 0;
+}
+
+bool ESP32::open(const char *type, int id, const char* addr, int port, int opt)
+{
+    bool ret;
+
+    if (id >= SOCKET_COUNT) {
+        return false;
+    }
+    _cbs[id].Notified = 0;
+
+    _smutex.lock();
+    startup();
+    setTimeout(500);
+    if (opt != 0) {
+        ret = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d, %d", id, type, addr, port, opt)
+           && _parser.recv("OK");
+    } else {
+        ret = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
+           && _parser.recv("OK");
+    }
+    setTimeout();
+    _smutex.unlock();
+
+    return ret;
+}
+
+bool ESP32::send(int id, const void *data, uint32_t amount)
+{
+    int send_size;
+    bool ret;
+    int error_cnt = 0;
+    int index = 0;
+
+    _cbs[id].Notified = 0;
+    if (amount == 0) {
+        return true;
+    }
+
+    //May take a second try if device is busy
+    while (error_cnt < 2) {
+        if (((_id_bits & (1 << id)) == 0)
+         || ((_id_bits_close & (1 << id)) != 0)) {
+            return false;
+        }
+        send_size = amount;
+        if (send_size > 2048) {
+            send_size = 2048;
+        }
+        _smutex.lock();
+        startup();
+        ret = _parser.send("AT+CIPSEND=%d,%d", id, send_size)
+           && _parser.recv(">")
+           && (_parser.write((char*)data + index, (int)send_size) >= 0)
+           && _parser.recv("SEND OK");
+        _smutex.unlock();
+        if (ret) {
+            amount -= send_size;
+            index += send_size;
+            error_cnt = 0;
+            if (amount == 0) {
+                return true;
+            }
+        } else {
+            error_cnt++;
+        }
+    }
+
+    return false;
+}
+
+void ESP32::_packet_handler()
+{
+    int id;
+    int amount;
+
+    startup();
+    // parse out the packet
+    if (!_parser.recv(",%d,%d:", &id, &amount)) {
+        return;
+    }
+
+    struct packet *packet = (struct packet*)malloc(
+            sizeof(struct packet) + amount);
+    if (!packet) {
+        return;
+    }
+
+    packet->id = id;
+    packet->len = amount;
+    packet->next = 0;
+    packet->index = 0;
+
+    if (!(_parser.read((char*)(packet + 1), amount))) {
+        free(packet);
+        setTimeout();
+        return;
+    }
+
+    // append to packet list
+    *_packets_end = packet;
+    _packets_end = &packet->next;
+}
+
+int32_t ESP32::recv(int id, void *data, uint32_t amount, uint32_t timeout)
+{
+    _cbs[id].Notified = 0;
+
+    _smutex.lock();
+    setTimeout(timeout);
+    _parser.process_oob(); // Poll for inbound packets
+    setTimeout();
+
+    // check if any packets are ready for us
+    for (struct packet **p = &_packets; *p; p = &(*p)->next) {
+        if ((*p)->id == id) {
+            struct packet *q = *p;
+
+            if (q->len <= amount) { // Return and remove full packet
+                memcpy(data, (uint8_t*)(q+1) + q->index, q->len);
+
+                if (_packets_end == &(*p)->next) {
+                    _packets_end = p;
+                }
+                *p = (*p)->next;
+                _smutex.unlock();
+
+                uint32_t len = q->len;
+                free(q);
+                return len;
+            } else { // return only partial packet
+                memcpy(data, (uint8_t*)(q+1) + q->index, amount);
+
+                q->len -= amount;
+                q->index += amount;
+
+                _smutex.unlock();
+                return amount;
+            }
+        }
+    }
+    _smutex.unlock();
+
+    if (((_id_bits & (1 << id)) == 0)
+     || ((_id_bits_close & (1 << id)) != 0)) {
+        return -2;
+    } else {
+        return -1;
+    }
+}
+
+bool ESP32::close(int id, bool wait_close)
+{
+    if (wait_close) {
+        for (int j = 0; j < 2; j++) {
+            if (((_id_bits & (1 << id)) == 0)
+             || ((_id_bits_close & (1 << id)) != 0)) {
+                _id_bits_close &= ~(1 << id);
+                _ids[id] = false;
+                return true;
+            }
+            _smutex.lock();
+            startup();
+            setTimeout(500);
+            _parser.process_oob(); // Poll for inbound packets
+            setTimeout();
+        }
+    }
+
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if ((_id_bits & (1 << id)) == 0) {
+            _id_bits_close &= ~(1 << id);
+            _ids[id] = false;
+            return true;
+        }
+        _smutex.lock();
+        startup();
+        setTimeout(500);
+        if (_parser.send("AT+CIPCLOSE=%d", id)
+            && _parser.recv("OK")) {
+            setTimeout();
+            _smutex.unlock();
+            _id_bits_close &= ~(1 << id);
+            _ids[id] = false;
+            return true;
+        }
+        setTimeout();
+        _smutex.unlock();
+    }
+
+    _ids[id] = false;
+    return false;
+}
+
+void ESP32::setTimeout(uint32_t timeout_ms)
+{
+    _parser.set_timeout(timeout_ms);
+}
+
+bool ESP32::readable()
+{
+    return _serial.FileHandle::readable();
+}
+
+bool ESP32::writeable()
+{
+    return _serial.FileHandle::writable();
+}
+
+void ESP32::socket_attach(int id, void (*callback)(void *), void *data)
+{
+    _cbs[id].callback = callback;
+    _cbs[id].data = data;
+    _cbs[id].Notified = 0;
+}
+
+bool ESP32::recv_ap(nsapi_wifi_ap_t *ap)
+{
+    int sec;
+    bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu)", &sec, ap->ssid,
+                            &ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
+                            &ap->bssid[5], &ap->channel);
+
+    ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
+
+    return ret;
+}
+
+void ESP32::_connect_handler_0() { socket_handler(true, 0);  }
+void ESP32::_connect_handler_1() { socket_handler(true, 1);  }
+void ESP32::_connect_handler_2() { socket_handler(true, 2);  }
+void ESP32::_connect_handler_3() { socket_handler(true, 3);  }
+void ESP32::_connect_handler_4() { socket_handler(true, 4);  }
+void ESP32::_closed_handler_0()  { socket_handler(false, 0); }
+void ESP32::_closed_handler_1()  { socket_handler(false, 1); }
+void ESP32::_closed_handler_2()  { socket_handler(false, 2); }
+void ESP32::_closed_handler_3()  { socket_handler(false, 3); }
+void ESP32::_closed_handler_4()  { socket_handler(false, 4); }
+
+void ESP32::_connection_status_handler()
+{
+    char status[13];
+    if (_parser.recv("%12[^\"]\n", status)) {
+        if (strcmp(status, "CONNECTED\n") == 0) {
+            _wifi_status = STATUS_CONNECTED;
+        } else if (strcmp(status, "GOT IP\n") == 0) {
+            _wifi_status = STATUS_GOT_IP;
+        } else if (strcmp(status, "DISCONNECT\n") == 0) {
+            _wifi_status = STATUS_DISCONNECTED;
+        } else {
+            return;
+        }
+
+        if(_wifi_status_cb) {
+            _wifi_status_cb(_wifi_status);
+        }
+    }
+}
+
+int ESP32::get_free_id()
+{
+    // Look for an unused socket
+    int id = -1;
+
+    for (int i = 0; i < SOCKET_COUNT; i++) {
+        if ((!_ids[i]) && ((_id_bits & (1 << i)) == 0)) {
+            id = i;
+            _ids[i] = true;
+            break;
+        }
+    }
+
+    return id;
+}
+
+void ESP32::event() {
+    for (int i = 0; i < SOCKET_COUNT; i++) {
+        if ((_cbs[i].callback) && (_cbs[i].Notified == 0)) {
+            _cbs[i].callback(_cbs[i].data);
+            _cbs[i].Notified = 1;
+        }
+    }
+}
+
+bool ESP32::set_network(const char *ip_address, const char *netmask, const char *gateway)
+{
+    bool ret;
+
+    if (ip_address == NULL) {
+        return false;
+    }
+
+    _smutex.lock();
+    if ((netmask != NULL) && (gateway != NULL)) {
+        ret = _parser.send("AT+CIPSTA=\"%s\",\"%s\",\"%s\"", ip_address, gateway, netmask)
+           && _parser.recv("OK");
+    } else {
+        ret = _parser.send("AT+CIPSTA=\"%s\"", ip_address)
+           && _parser.recv("OK");
+    }
+    _smutex.unlock();
+
+    return ret;
+}
+
+bool ESP32::set_network_ap(const char *ip_address, const char *netmask, const char *gateway)
+{
+    bool ret;
+
+    if (ip_address == NULL) {
+        return false;
+    }
+
+    _smutex.lock();
+    if ((netmask != NULL) && (gateway != NULL)) {
+        ret = _parser.send("AT+CIPAP=\"%s\",\"%s\",\"%s\"", ip_address, gateway, netmask)
+           && _parser.recv("OK");
+    } else {
+        ret = _parser.send("AT+CIPAP=\"%s\"", ip_address)
+           && _parser.recv("OK");
+    }
+    _smutex.unlock();
+
+    return ret;
+}
+
+void ESP32::attach_wifi_status(mbed::Callback<void(int8_t)> status_cb)
+{
+    _wifi_status_cb = status_cb;
+}
+
+int8_t ESP32::get_wifi_status() const
+{
+    return _wifi_status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32/ESP32.h	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,299 @@
+/* ESP32Interface Example
+ * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ESP32_H
+#define ESP32_H
+
+#include <vector>
+#include "ATCmdParser.h"
+
+#ifndef ESP32_CONNECT_TIMEOUT
+#define ESP32_CONNECT_TIMEOUT 15000
+#endif
+#ifndef ESP32_RECV_TIMEOUT
+#define ESP32_RECV_TIMEOUT    2000
+#endif
+#ifndef ESP32_MISC_TIMEOUT
+#define ESP32_MISC_TIMEOUT    2000
+#endif
+
+/** ESP32Interface class.
+    This is an interface to a ESP32 radio.
+ */
+class ESP32
+{
+public:
+    /**
+    * Static method to create or retrieve the single ESP32 instance
+    */
+    static ESP32 * getESP32Inst(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate);
+
+    ESP32(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate);
+
+    /**
+    * Check firmware version of ESP8266
+    *
+    * @return integer firmware version or -1 if firmware query command gives outdated response
+    */
+    int get_firmware_version(void);
+
+    /**
+    * Sets the Wi-Fi Mode
+    *
+    * @param mode mode of WIFI 1-client, 2-host, 3-both
+    * @return true only if ESP32 was setup correctly
+    */
+    bool set_mode(int mode);
+
+    /**
+    * Enable/Disable DHCP
+    *
+    * @param enabled DHCP enabled when true
+    * @param mode mode of DHCP 0-softAP, 1-station, 2-both
+    * @return true only if ESP32 enables/disables DHCP successfully
+    */
+    bool dhcp(bool enabled, int mode);
+
+    /**
+    * Connect ESP32 to AP
+    *
+    * @param ap the name of the AP
+    * @param passPhrase the password of AP
+    * @return true only if ESP32 is connected successfully
+    */
+    bool connect(const char *ap, const char *passPhrase);
+
+    /**
+    * Disconnect ESP32 from AP
+    *
+    * @return true only if ESP32 is disconnected successfully
+    */
+    bool disconnect(void);
+
+    /**
+    * Get the IP address of ESP32
+    *
+    * @return null-teriminated IP address or null if no IP address is assigned
+    */
+    const char *getIPAddress(void);
+    const char *getIPAddress_ap(void);
+
+    /**
+    * Get the MAC address of ESP32
+    *
+    * @return null-terminated MAC address or null if no MAC address is assigned
+    */
+    const char *getMACAddress(void);
+    const char *getMACAddress_ap(void);
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    const char *getGateway();
+    const char *getGateway_ap();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask 
+     *                  or null if no network mask has been recieved
+     */
+    const char *getNetmask();
+    const char *getNetmask_ap();
+
+    /* Return RSSI for active connection
+     *
+     * @return      Measured RSSI
+     */
+    int8_t getRSSI();
+
+    /**
+    * Check if ESP32 is conenected
+    *
+    * @return true only if the chip has an IP address
+    */
+    bool isConnected(void);
+
+    /** Scan for available networks
+     *
+     * @param  ap    Pointer to allocated array to store discovered AP
+     * @param  limit Size of allocated @a res array, or 0 to only count available AP
+     * @return       Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
+     *               see @a nsapi_error
+     */
+    int scan(WiFiAccessPoint *res, unsigned limit);
+
+    /**
+    * Open a socketed connection
+    *
+    * @param type the type of socket to open "UDP" or "TCP"
+    * @param id id to give the new socket, valid 0-4
+    * @param port port to open connection with
+    * @param addr the IP address of the destination
+    * @param addr the IP address of the destination
+    * @param opt  type=" UDP" : UDP socket's local port, zero means any
+    *             type=" TCP" : TCP connection's keep alive time, zero means disabled
+    * @return true only if socket opened successfully
+    */
+    bool open(const char *type, int id, const char* addr, int port, int opt = 0);
+
+    /**
+    * Sends data to an open socket
+    *
+    * @param id id of socket to send to
+    * @param data data to be sent
+    * @param amount amount of data to be sent - max 1024
+    * @return true only if data sent successfully
+    */
+    bool send(int id, const void *data, uint32_t amount);
+
+    /**
+    * Receives data from an open socket
+    *
+    * @param id id to receive from
+    * @param data placeholder for returned information
+    * @param amount number of bytes to be received
+    * @return the number of bytes received
+    */
+    int32_t recv(int id, void *data, uint32_t amount, uint32_t timeout = ESP32_RECV_TIMEOUT);
+
+    /**
+    * Closes a socket
+    *
+    * @param id id of socket to close, valid only 0-4
+    * @param wait_close 
+    * @return true only if socket is closed successfully
+    */
+    bool close(int id, bool wait_close = false);
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout_ms timeout of the connection
+    */
+    void setTimeout(uint32_t timeout_ms = ESP32_MISC_TIMEOUT);
+
+    /**
+    * Checks if data is available
+    */
+    bool readable();
+
+    /**
+    * Checks if data can be written
+    */
+    bool writeable();
+
+    void socket_attach(int id, void (*callback)(void *), void *data);
+    int get_free_id();
+
+    bool config_soft_ap(const char *ap, const char *passPhrase, uint8_t chl, uint8_t ecn);
+
+    bool restart();
+    bool get_ssid(char *ap);
+    bool cre_server(int port);
+    bool del_server();
+    bool accept(int * p_id);
+
+    bool set_network(const char *ip_address, const char *netmask, const char *gateway);
+    bool set_network_ap(const char *ip_address, const char *netmask, const char *gateway);
+
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param func A pointer to a void function, or 0 to set as none
+    */
+    void attach_wifi_status(mbed::Callback<void(int8_t)> status_cb);
+
+    /** Get the connection status
+     *
+     *  @return         The connection status according to ConnectionStatusType
+     */
+    int8_t get_wifi_status() const;
+
+    static const int8_t WIFIMODE_STATION = 1;
+    static const int8_t WIFIMODE_SOFTAP = 2;
+    static const int8_t WIFIMODE_STATION_SOFTAP = 3;
+    static const int8_t SOCKET_COUNT = 5;
+
+    static const int8_t STATUS_DISCONNECTED = 0;
+    static const int8_t STATUS_CONNECTED = 1;
+    static const int8_t STATUS_GOT_IP = 2;
+
+private:
+    DigitalOut * _p_wifi_en;
+    DigitalOut * _p_wifi_io0;
+    bool init_end;
+    UARTSerial _serial;
+    ATCmdParser _parser;
+    struct packet {
+        struct packet *next;
+        int id;
+        uint32_t len;
+        uint32_t index;
+        // data follows
+    } *_packets, **_packets_end;
+    int _wifi_mode;
+    int _baudrate;
+
+    std::vector<int> _accept_id;
+    uint32_t _id_bits;
+    uint32_t _id_bits_close;
+    bool _server_act;
+    rtos::Mutex _smutex; // Protect serial port access
+    static ESP32 * instESP32;
+    int8_t _wifi_status;
+    Callback<void(int8_t)> _wifi_status_cb;
+
+    bool _ids[SOCKET_COUNT];
+    struct {
+        void (*callback)(void *);
+        void *data;
+        int  Notified;
+    } _cbs[SOCKET_COUNT];
+
+    bool startup();
+    bool reset(void);
+    void debugOn(bool debug);
+    void socket_handler(bool connect, int id);
+    void _connect_handler_0();
+    void _connect_handler_1();
+    void _connect_handler_2();
+    void _connect_handler_3();
+    void _connect_handler_4();
+    void _closed_handler_0();
+    void _closed_handler_1();
+    void _closed_handler_2();
+    void _closed_handler_3();
+    void _closed_handler_4();
+    void _connection_status_handler();
+    void _packet_handler();
+    void event();
+    bool recv_ap(nsapi_wifi_ap_t *ap);
+
+    char _ip_buffer[16];
+    char _gateway_buffer[16];
+    char _netmask_buffer[16];
+    char _mac_buffer[18];
+
+    char _ip_buffer_ap[16];
+    char _gateway_buffer_ap[16];
+    char _netmask_buffer_ap[16];
+    char _mac_buffer_ap[18];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32Interface.cpp	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,196 @@
+/* ESP32 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "ESP32Interface.h"
+
+// ESP32Interface implementation
+ESP32Interface::ESP32Interface(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate) :
+    ESP32Stack(en, io0, tx, rx, debug, baudrate),
+     _dhcp(true),
+    _ap_ssid(),
+    _ap_pass(),
+    _ap_sec(NSAPI_SECURITY_NONE),
+    _ip_address(),
+    _netmask(),
+    _gateway(),
+    _connection_status(NSAPI_STATUS_DISCONNECTED),
+    _connection_status_cb(NULL)
+{
+    _esp->attach_wifi_status(callback(this, &ESP32Interface::wifi_status_cb));
+}
+
+ESP32Interface::ESP32Interface(PinName tx, PinName rx, bool debug, int baudrate) :
+    ESP32Stack(NC, NC, tx, rx, debug, baudrate),
+     _dhcp(true),
+    _ap_ssid(),
+    _ap_pass(),
+    _ap_sec(NSAPI_SECURITY_NONE),
+    _ip_address(),
+    _netmask(),
+    _gateway(),
+    _connection_status(NSAPI_STATUS_DISCONNECTED),
+    _connection_status_cb(NULL)
+{
+    _esp->attach_wifi_status(callback(this, &ESP32Interface::wifi_status_cb));
+}
+
+nsapi_error_t ESP32Interface::set_network(const char *ip_address, const char *netmask, const char *gateway)
+{
+    _dhcp = false;
+
+    strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address));
+    _ip_address[sizeof(_ip_address) - 1] = '\0';
+    strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask));
+    _netmask[sizeof(_netmask) - 1] = '\0';
+    strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway));
+    _gateway[sizeof(_gateway) - 1] = '\0';
+
+    return NSAPI_ERROR_OK;
+}
+
+nsapi_error_t ESP32Interface::set_dhcp(bool dhcp)
+{
+    _dhcp = dhcp;
+
+    return NSAPI_ERROR_OK;
+}
+
+int ESP32Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                                        uint8_t channel)
+{
+    if (channel != 0) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    set_credentials(ssid, pass, security);
+    return connect();
+}
+
+int ESP32Interface::connect()
+{
+    if (!_esp->dhcp(_dhcp, 1)) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    if (!_dhcp) {
+        if (!_esp->set_network(_ip_address, _netmask, _gateway)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+
+    set_connection_status(NSAPI_STATUS_CONNECTING);
+    if (!_esp->connect(_ap_ssid, _ap_pass)) {
+        set_connection_status(NSAPI_STATUS_DISCONNECTED);
+        return NSAPI_ERROR_NO_CONNECTION;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+int ESP32Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    memset(_ap_ssid, 0, sizeof(_ap_ssid));
+    strncpy(_ap_ssid, ssid, sizeof(_ap_ssid));
+
+    memset(_ap_pass, 0, sizeof(_ap_pass));
+    strncpy(_ap_pass, pass, sizeof(_ap_pass));
+
+    _ap_sec = security;
+
+    return 0;
+}
+
+int ESP32Interface::set_channel(uint8_t channel)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ESP32Interface::disconnect()
+{
+    if (!_esp->disconnect()) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+const char *ESP32Interface::get_ip_address()
+{
+    return _esp->getIPAddress();
+}
+
+const char *ESP32Interface::get_mac_address()
+{
+    return _esp->getMACAddress();
+}
+
+const char *ESP32Interface::get_gateway()
+{
+    return _esp->getGateway();
+}
+
+const char *ESP32Interface::get_netmask()
+{
+    return _esp->getNetmask();
+}
+
+int8_t ESP32Interface::get_rssi()
+{
+    return _esp->getRSSI();
+}
+
+int ESP32Interface::scan(WiFiAccessPoint *res, unsigned count)
+{
+    return _esp->scan(res, count);
+}
+
+void ESP32Interface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
+{
+    _connection_status_cb = status_cb;
+}
+
+nsapi_connection_status_t ESP32Interface::get_connection_status() const
+{
+    return _connection_status;
+}
+
+void ESP32Interface::set_connection_status(nsapi_connection_status_t connection_status)
+{
+    if (_connection_status != connection_status) {
+        _connection_status = connection_status;
+        if (_connection_status_cb) {
+            _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status);
+        }
+    }
+}
+
+void ESP32Interface::wifi_status_cb(int8_t wifi_status)
+{
+    switch (wifi_status) {
+        case ESP32::STATUS_DISCONNECTED:
+            set_connection_status(NSAPI_STATUS_DISCONNECTED);
+            break;
+        case ESP32::STATUS_GOT_IP:
+            set_connection_status(NSAPI_STATUS_GLOBAL_UP);
+            break;
+        case ESP32::STATUS_CONNECTED:
+        default:
+            // do nothing
+            break;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32Interface.h	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,227 @@
+/* ESP32 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ESP32_INTERFACE_H
+#define ESP32_INTERFACE_H
+
+#include "mbed.h"
+#include "ESP32Stack.h"
+
+/** ESP32Interface class
+ *  Implementation of the NetworkStack for the ESP32
+ */
+class ESP32Interface : public ESP32Stack, public WiFiInterface
+{
+public:
+    /** ESP32Interface lifetime
+     * @param en        EN pin  (If not used this pin, please set "NC")
+     * @param io0       IO0 pin (If not used this pin, please set "NC")
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param debug     Enable debugging
+     * @param baudrate  The baudrate of the serial port (default = 230400).
+     */
+    ESP32Interface(PinName en, PinName io0, PinName tx, PinName rx, bool debug = false, int baudrate = 230400);
+
+    /** ESP32Interface lifetime
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param debug     Enable debugging
+     * @param baudrate  The baudrate of the serial port (default = 230400).
+     */
+    ESP32Interface(PinName tx, PinName rx, bool debug = false, int baudrate = 230400);
+
+    /** Set a static IP address
+     *
+     *  Configures this network interface to use a static IP address.
+     *  Implicitly disables DHCP, which can be enabled in set_dhcp.
+     *  Requires that the network is disconnected.
+     *
+     *  @param ip_address Null-terminated representation of the local IP address
+     *  @param netmask    Null-terminated representation of the local network mask
+     *  @param gateway    Null-terminated representation of the local gateway
+     *  @return           0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t set_network(
+            const char *ip_address, const char *netmask, const char *gateway);
+
+    /** Enable or disable DHCP on the network
+     *
+     *  Enables DHCP on connecting the network. Defaults to enabled unless
+     *  a static IP address has been assigned. Requires that the network is
+     *  disconnected.
+     *
+     *  @param dhcp     True to enable DHCP
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t set_dhcp(bool dhcp);
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
+     *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int connect();
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network.
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
+     *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
+                                  uint8_t channel = 0);
+
+    /** Set the WiFi network credentials
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection
+     *                   (defaults to NSAPI_SECURITY_NONE)
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    /** Set the WiFi network channel - NOT SUPPORTED
+     *
+     * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
+     *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual int set_channel(uint8_t channel);
+
+    /** Stop the interface
+     *  @return             0 on success, negative on failure
+     */
+    virtual int disconnect();
+
+    /** Get the internally stored IP address
+     *  @return             IP address of the interface or null if not yet connected
+     */
+    virtual const char *get_ip_address();
+
+    /** Get the internally stored MAC address
+     *  @return             MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_gateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_netmask();
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    virtual int8_t get_rssi();
+
+    /** Scan for available networks
+     *
+     * This function will block.
+     *
+     * @param  ap       Pointer to allocated array to store discovered AP
+     * @param  count    Size of allocated @a res array, or 0 to only count available AP
+     * @param  timeout  Timeout in milliseconds; 0 for no timeout (Default: 0)
+     * @return          Number of entries in @a, or if @a count was 0 number of available networks, negative on error
+     *                  see @a nsapi_error
+     */
+    virtual int scan(WiFiAccessPoint *res, unsigned count);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *  If no stack-specific DNS resolution is provided, the hostname
+     *  will be resolve using a UDP socket on the stack.
+     *
+     *  @param address  Destination for the host SocketAddress
+     *  @param host     Hostname to resolve
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::gethostbyname;
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::add_dns_server;
+
+    /** Register callback for status reporting
+     *
+     *  The specified status callback function will be called on status changes
+     *  on the network. The parameters on the callback are the event type and
+     *  event-type dependent reason parameter.
+     *
+     *  In ESP32 the callback will be called when processing OOB-messages via
+     *  AT-parser. Do NOT call any ESP8266Interface -functions or do extensive
+     *  processing in the callback.
+     *
+     *  @param status_cb The callback for status changes
+     */
+    virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
+
+    /** Get the connection status
+     *
+     *  @return         The connection status according to ConnectionStatusType
+     */
+    virtual nsapi_connection_status_t get_connection_status() const;
+
+    /** Provide access to the NetworkStack object
+     *
+     *  @return The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack()
+    {
+        return this;
+    }
+
+private:
+    bool _dhcp;
+    char _ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    char _ap_pass[64]; /* The longest allowed passphrase */
+    nsapi_security_t _ap_sec;
+    char _ip_address[NSAPI_IPv6_SIZE];
+    char _netmask[NSAPI_IPv4_SIZE];
+    char _gateway[NSAPI_IPv4_SIZE];
+    nsapi_connection_status_t _connection_status;
+    Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
+
+    void set_connection_status(nsapi_connection_status_t connection_status);
+    void wifi_status_cb(int8_t wifi_status);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32InterfaceAP.cpp	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,204 @@
+/* ESP32 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "ESP32InterfaceAP.h"
+
+// ESP32InterfaceAP implementation
+ESP32InterfaceAP::ESP32InterfaceAP(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate) :
+    ESP32Stack(en, io0, tx, rx, debug, baudrate),
+    _dhcp(true),
+    _own_ch(1),
+    _own_ssid(),
+    _own_pass(),
+    _own_sec(NSAPI_SECURITY_NONE),
+    _ip_address(),
+    _netmask(),
+    _gateway(),
+    _connection_status(NSAPI_STATUS_DISCONNECTED),
+    _connection_status_cb(NULL)
+{
+}
+
+ESP32InterfaceAP::ESP32InterfaceAP(PinName tx, PinName rx, bool debug, int baudrate) :
+    ESP32Stack(NC, NC, tx, rx, debug, baudrate),
+    _dhcp(true),
+    _own_ch(1),
+    _own_ssid(),
+    _own_pass(),
+    _own_sec(NSAPI_SECURITY_NONE),
+    _ip_address(),
+    _netmask(),
+    _gateway(),
+    _connection_status(NSAPI_STATUS_DISCONNECTED),
+    _connection_status_cb(NULL)
+{
+}
+
+nsapi_error_t ESP32InterfaceAP::set_network(const char *ip_address, const char *netmask, const char *gateway)
+{
+    _dhcp = false;
+
+    strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address));
+    _ip_address[sizeof(_ip_address) - 1] = '\0';
+    strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask));
+    _netmask[sizeof(_netmask) - 1] = '\0';
+    strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway));
+    _gateway[sizeof(_gateway) - 1] = '\0';
+
+    return NSAPI_ERROR_OK;
+}
+
+nsapi_error_t ESP32InterfaceAP::set_dhcp(bool dhcp)
+{
+    _dhcp = dhcp;
+
+    return NSAPI_ERROR_OK;
+}
+
+int ESP32InterfaceAP::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                                        uint8_t channel)
+{
+    int ret;
+
+    ret = set_credentials(ssid, pass, security);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = set_channel(channel);
+    if (ret != 0) {
+        return ret;
+    }
+
+    return connect();
+}
+
+int ESP32InterfaceAP::connect()
+{
+    if (!_esp->set_mode(ESP32::WIFIMODE_STATION_SOFTAP)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    if (!_esp->dhcp(_dhcp, 1)) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    if (!_dhcp) {
+        if (!_esp->set_network_ap(_ip_address, _netmask, _gateway)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+
+    if (!_esp->config_soft_ap(_own_ssid, _own_pass, _own_ch, (uint8_t)_own_sec)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _connection_status = NSAPI_STATUS_GLOBAL_UP;
+    if (_connection_status_cb) {
+        _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status);
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+int ESP32InterfaceAP::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    switch (security) {
+        case NSAPI_SECURITY_NONE:
+        case NSAPI_SECURITY_WPA:
+        case NSAPI_SECURITY_WPA2:
+        case NSAPI_SECURITY_WPA_WPA2:
+            _own_sec = security;
+            break;
+        case NSAPI_SECURITY_UNKNOWN:
+        case NSAPI_SECURITY_WEP:
+        default:
+            return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    memset(_own_ssid, 0, sizeof(_own_ssid));
+    strncpy(_own_ssid, ssid, sizeof(_own_ssid));
+
+    memset(_own_pass, 0, sizeof(_own_pass));
+    strncpy(_own_pass, pass, sizeof(_own_pass));
+
+    return 0;
+}
+
+int ESP32InterfaceAP::set_channel(uint8_t channel)
+{
+    if (channel != 0) {
+        _own_ch = channel;
+    }
+
+    return 0;
+}
+
+int ESP32InterfaceAP::disconnect()
+{
+    if (!_esp->set_mode(ESP32::WIFIMODE_STATION)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _connection_status = NSAPI_STATUS_DISCONNECTED;
+    if (_connection_status_cb) {
+        _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status);
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+const char *ESP32InterfaceAP::get_ip_address()
+{
+    return _esp->getIPAddress_ap();
+}
+
+const char *ESP32InterfaceAP::get_mac_address()
+{
+    return _esp->getMACAddress_ap();
+}
+
+const char *ESP32InterfaceAP::get_gateway()
+{
+    return _esp->getGateway_ap();
+}
+
+const char *ESP32InterfaceAP::get_netmask()
+{
+    return _esp->getNetmask_ap();
+}
+
+int8_t ESP32InterfaceAP::get_rssi()
+{
+    return 0;
+}
+
+int ESP32InterfaceAP::scan(WiFiAccessPoint *res, unsigned count)
+{
+    return _esp->scan(res, count);
+}
+
+void ESP32InterfaceAP::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
+{
+    _connection_status_cb = status_cb;
+}
+
+nsapi_connection_status_t ESP32InterfaceAP::get_connection_status() const
+{
+    return _connection_status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32InterfaceAP.h	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,227 @@
+/* ESP32 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ESP32_INTERFACE_AP_H
+#define ESP32_INTERFACE_AP_H
+
+#include "mbed.h"
+#include "ESP32Stack.h"
+
+
+/** ESP32Interface class
+ *  Implementation of the NetworkStack for the ESP32
+ */
+class ESP32InterfaceAP : public ESP32Stack, public WiFiInterface
+{
+public:
+    /** ESP32InterfaceAP lifetime
+     * @param en        EN pin  (If not used this pin, please set "NC")
+     * @param io0       IO0 pin (If not used this pin, please set "NC")
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param debug     Enable debugging
+     * @param baudrate  The baudrate of the serial port (default = 230400).
+     */
+    ESP32InterfaceAP(PinName en, PinName io0, PinName tx, PinName rx, bool debug = false, int baudrate = 230400);
+
+    /** ESP32InterfaceAP lifetime
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param debug     Enable debugging
+     * @param baudrate  The baudrate of the serial port (default = 230400).
+     */
+    ESP32InterfaceAP(PinName tx, PinName rx, bool debug = false, int baudrate = 230400);
+
+    /** Set a static IP address
+     *
+     *  Configures this network interface to use a static IP address.
+     *  Implicitly disables DHCP, which can be enabled in set_dhcp.
+     *  Requires that the network is disconnected.
+     *
+     *  @param ip_address Null-terminated representation of the local IP address
+     *  @param netmask    Null-terminated representation of the local network mask
+     *  @param gateway    Null-terminated representation of the local gateway
+     *  @return           0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t set_network(
+            const char *ip_address, const char *netmask, const char *gateway);
+
+    /** Enable or disable DHCP on the network
+     *
+     *  Enables DHCP on connecting the network. Defaults to enabled unless
+     *  a static IP address has been assigned. Requires that the network is
+     *  disconnected.
+     *
+     *  @param dhcp     True to enable DHCP
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t set_dhcp(bool dhcp);
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
+     *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int connect();
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network.
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
+     *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
+                                  uint8_t channel = 0);
+
+    /** Set the WiFi network credentials
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection
+     *                   (defaults to NSAPI_SECURITY_NONE)
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    /** Set the WiFi network channel - NOT SUPPORTED
+     *
+     * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
+     *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual int set_channel(uint8_t channel);
+
+    /** Stop the interface
+     *  @return             0 on success, negative on failure
+     */
+    virtual int disconnect();
+
+    /** Get the internally stored IP address
+     *  @return             IP address of the interface or null if not yet connected
+     */
+    virtual const char *get_ip_address();
+
+    /** Get the internally stored MAC address
+     *  @return             MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_gateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_netmask();
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    virtual int8_t get_rssi();
+
+    /** Scan for available networks
+     *
+     * This function will block.
+     *
+     * @param  ap       Pointer to allocated array to store discovered AP
+     * @param  count    Size of allocated @a res array, or 0 to only count available AP
+     * @param  timeout  Timeout in milliseconds; 0 for no timeout (Default: 0)
+     * @return          Number of entries in @a, or if @a count was 0 number of available networks, negative on error
+     *                  see @a nsapi_error
+     */
+    virtual int scan(WiFiAccessPoint *res, unsigned count);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *  If no stack-specific DNS resolution is provided, the hostname
+     *  will be resolve using a UDP socket on the stack.
+     *
+     *  @param address  Destination for the host SocketAddress
+     *  @param host     Hostname to resolve
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::gethostbyname;
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::add_dns_server;
+
+    /** Register callback for status reporting
+     *
+     *  The specified status callback function will be called on status changes
+     *  on the network. The parameters on the callback are the event type and
+     *  event-type dependent reason parameter.
+     *
+     *  In ESP32 the callback will be called when processing OOB-messages via
+     *  AT-parser. Do NOT call any ESP8266Interface -functions or do extensive
+     *  processing in the callback.
+     *
+     *  @param status_cb The callback for status changes
+     */
+    virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
+
+    /** Get the connection status
+     *
+     *  @return         The connection status according to ConnectionStatusType
+     */
+    virtual nsapi_connection_status_t get_connection_status() const;
+
+
+    /** Provide access to the NetworkStack object
+     *
+     *  @return The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack()
+    {
+        return this;
+    }
+
+private:
+    bool _dhcp;
+    uint8_t _own_ch;
+    char _own_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    char _own_pass[64]; /* The longest allowed passphrase */
+    nsapi_security_t _own_sec;
+    char _ip_address[NSAPI_IPv6_SIZE];
+    char _netmask[NSAPI_IPv4_SIZE];
+    char _gateway[NSAPI_IPv4_SIZE];
+    nsapi_connection_status_t _connection_status;
+    Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32Stack.cpp	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,326 @@
+/* ESP32 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "ESP32Stack.h"
+
+// ESP32Stack implementation
+ESP32Stack::ESP32Stack(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate)
+{
+    _esp = ESP32::getESP32Inst(en, io0, tx, rx, debug, baudrate);
+    memset(_local_ports, 0, sizeof(_local_ports));
+}
+
+struct esp32_socket {
+    int id;
+    nsapi_protocol_t proto;
+    bool connected;
+    SocketAddress addr;
+    int keepalive; // TCP
+    bool accept_id;
+    bool tcp_server;
+};
+
+int ESP32Stack::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    // Look for an unused socket
+    int id = _esp->get_free_id();
+
+    if (id == -1) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    struct esp32_socket *socket = new struct esp32_socket;
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    socket->id = id;
+    socket->proto = proto;
+    socket->connected = false;
+    socket->keepalive = 0;
+    socket->accept_id = false;
+    socket->tcp_server = false;
+    *handle = socket;
+    return 0;
+}
+
+int ESP32Stack::socket_close(void *handle)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+    int err = 0;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (!_esp->close(socket->id, socket->accept_id)) {
+        err = NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    if (socket->tcp_server) {
+        _esp->del_server();
+    }
+    _local_ports[socket->id] = 0;
+
+    delete socket;
+    return err;
+}
+
+int ESP32Stack::socket_bind(void *handle, const SocketAddress &address)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (socket->proto == NSAPI_UDP) {
+        if(address.get_addr().version != NSAPI_UNSPEC) {
+            return NSAPI_ERROR_UNSUPPORTED;
+        }
+
+        for(int id = 0; id < ESP32::SOCKET_COUNT; id++) {
+            if(_local_ports[id] == address.get_port() && id != socket->id) { // Port already reserved by another socket
+                return NSAPI_ERROR_PARAMETER;
+            } else if (id == socket->id && socket->connected) {
+                return NSAPI_ERROR_PARAMETER;
+            }
+        }
+        _local_ports[socket->id] = address.get_port();
+        return 0;
+    }
+
+    socket->addr = address;
+    return 0;
+}
+
+int ESP32Stack::socket_listen(void *handle, int backlog)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    (void)backlog;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (socket->proto != NSAPI_TCP) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    if (!_esp->cre_server(socket->addr.get_port())) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    socket->tcp_server = true;
+    return 0;
+}
+
+int ESP32Stack::socket_connect(void *handle, const SocketAddress &addr)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (socket->proto == NSAPI_UDP) {
+        if (!_esp->open("UDP", socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id])) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    } else {
+        if (!_esp->open("TCP", socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+
+    socket->connected = true;
+    return 0;
+}
+
+int ESP32Stack::socket_accept(void *server, void **socket, SocketAddress *addr)
+{
+    struct esp32_socket *socket_new = new struct esp32_socket;
+    int id;
+
+    if (!socket_new) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (!_esp->accept(&id)) {
+        delete socket_new;
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    socket_new->id = id;
+    socket_new->proto = NSAPI_TCP;
+    socket_new->connected = true;
+    socket_new->accept_id = true;
+    socket_new->tcp_server = false;
+    *socket = socket_new;
+
+    return 0;
+}
+
+int ESP32Stack::socket_send(void *handle, const void *data, unsigned size)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (!_esp->send(socket->id, data, size)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    return size;
+}
+
+int ESP32Stack::socket_recv(void *handle, void *data, unsigned size)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    int32_t recv = _esp->recv(socket->id, data, size);
+    if (recv == -1) {
+        return NSAPI_ERROR_WOULD_BLOCK;
+    } else if (recv < 0) {
+        return NSAPI_ERROR_NO_SOCKET;
+    } else {
+        // do nothing
+    }
+
+    return recv;
+}
+
+int ESP32Stack::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (socket->connected && socket->addr != addr) {
+        if (!_esp->close(socket->id, socket->accept_id)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->connected = false;
+    }
+
+    if (!socket->connected) {
+        int err = socket_connect(socket, addr);
+        if (err < 0) {
+            return err;
+        }
+        socket->addr = addr;
+    }
+    
+    return socket_send(socket, data, size);
+}
+
+int ESP32Stack::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    int ret = socket_recv(socket, data, size);
+    if (ret >= 0 && addr) {
+        *addr = socket->addr;
+    }
+
+    return ret;
+}
+
+void ESP32Stack::socket_attach(void *handle, void (*callback)(void *), void *data)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!socket) {
+        return;
+    }
+
+    _esp->socket_attach(socket->id, callback, data);
+}
+
+nsapi_error_t ESP32Stack::setsockopt(nsapi_socket_t handle, int level, 
+        int optname, const void *optval, unsigned optlen)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!optlen) {
+        return NSAPI_ERROR_PARAMETER;
+    } else if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
+        switch (optname) {
+            case NSAPI_KEEPALIVE: {
+                if(socket->connected) {// ESP32 limitation, keepalive needs to be given before connecting
+                    return NSAPI_ERROR_UNSUPPORTED;
+                }
+
+                if (optlen == sizeof(int)) {
+                    int secs = *(int *)optval;
+                    if (secs  >= 0 && secs <= 7200) {
+                        socket->keepalive = secs;
+                        return NSAPI_ERROR_OK;
+                    }
+                }
+                return NSAPI_ERROR_PARAMETER;
+            }
+        }
+    }
+
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+nsapi_error_t ESP32Stack::getsockopt(nsapi_socket_t handle, int level,
+        int optname, void *optval, unsigned *optlen)
+{
+    struct esp32_socket *socket = (struct esp32_socket *)handle;
+
+    if (!optval || !optlen) {
+        return NSAPI_ERROR_PARAMETER;
+    } else if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
+        switch (optname) {
+            case NSAPI_KEEPALIVE: {
+                if(*optlen > sizeof(int)) {
+                    *optlen = sizeof(int);
+                }
+                memcpy(optval, &(socket->keepalive), *optlen);
+                return NSAPI_ERROR_OK;
+            }
+        }
+    }
+
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP32Stack.h	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,174 @@
+/* ESP32 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2017 Renesas Electronics Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ESP32_STACK_H
+#define ESP32_STACK_H
+
+#include "mbed.h"
+#include "ESP32.h"
+
+/** ESP32Stack class
+ *  Implementation of the NetworkStack for the ESP32
+ */
+class ESP32Stack : public NetworkStack
+{
+protected:
+    /** ESP32Stack lifetime
+     * @param en        EN pin
+     * @param io0       IO0 pin
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param debug     Enable debugging
+     * @param baudrate  The baudrate of the serial port.
+     */
+    ESP32Stack(PinName en, PinName io0, PinName tx, PinName rx, bool debug, int baudrate);
+
+protected:
+    /** Open a socket
+     *  @param handle       Handle in which to store new socket
+     *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_open(void **handle, nsapi_protocol_t proto);
+
+    /** Close the socket
+     *  @param handle       Socket handle
+     *  @return             0 on success, negative on failure
+     *  @note On failure, any memory associated with the socket must still
+     *        be cleaned up
+     */
+    virtual int socket_close(void *handle);
+
+    /** Bind a server socket to a specific port
+     *  @param handle       Socket handle
+     *  @param address      Local address to listen for incoming connections on
+     *  @return             0 on success, negative on failure.
+     */
+    virtual int socket_bind(void *handle, const SocketAddress &address);
+
+    /** Start listening for incoming connections
+     *  @param handle       Socket handle
+     *  @param backlog      Number of pending connections that can be queued up at any
+     *                      one time [Default: 1]
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_listen(void *handle, int backlog);
+
+    /** Connects this TCP socket to the server
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress to connect to
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_connect(void *handle, const SocketAddress &address);
+
+    /** Accept a new connection.
+     *  @param handle       Handle in which to store new socket
+     *  @param server       Socket handle to server to accept from
+     *  @return             0 on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_accept(void *handle, void **socket, SocketAddress *address);
+
+    /** Send data to the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer to send to the host
+     *  @param size         The length of the buffer to send
+     *  @return             Number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_send(void *handle, const void *data, unsigned size);
+
+    /** Receive data from the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer in which to store the data received from the host
+     *  @param size         The maximum length of the buffer
+     *  @return             Number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recv(void *handle, void *data, unsigned size);
+
+    /** Send a packet to a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      The remote SocketAddress
+     *  @param data         The packet to be sent
+     *  @param size         The length of the packet to be sent
+     *  @return             The number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
+
+    /** Receive a packet from a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      Destination for the remote SocketAddress or null
+     *  @param buffer       The buffer for storing the incoming packet data
+     *                      If a packet is too long to fit in the supplied buffer,
+     *                      excess bytes are discarded
+     *  @param size         The length of the buffer
+     *  @return             The number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
+
+    /** Register a callback on state change of the socket
+     *  @param handle       Socket handle
+     *  @param callback     Function to call on state change
+     *  @param data         Argument to pass to callback
+     *  @note Callback may be called in an interrupt context.
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
+
+    /** Set stack-specific socket options
+     *  The setsockopt allow an application to pass stack-specific hints
+     *  to the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
+     *
+     *  @param handle   Socket handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t setsockopt(nsapi_socket_t handle, int level,
+            int optname, const void *optval, unsigned optlen);
+
+    /** Get stack-specific socket options
+     *  The getstackopt allow an application to retrieve stack-specific hints
+     *  from the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
+     *
+     *  @param handle   Socket handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Destination for option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level,
+            int optname, void *optval, unsigned *optlen);
+
+protected:
+    ESP32 *_esp;
+    uint16_t _local_ports[ESP32::SOCKET_COUNT];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Fri Jun 29 06:17:38 2018 +0000
@@ -0,0 +1,10 @@
+# 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.