mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #11409 from dmaziec1/esp8266-nonblocking
esp8266 nonblocking connect/disconnectpull/11460/head
						commit
						ac7b851ba0
					
				| 
						 | 
				
			
			@ -62,7 +62,7 @@ Please refer to the following table for priorities of test cases. Priorities are
 | 
			
		|||
| 9   | WIFI_CONNECT_PARAMS_CHANNEL             |                            | SHOULD   |
 | 
			
		||||
| 10  | WIFI_CONNECT_PARAMS_CHANNEL_FAIL        |                            | SHOULD   |
 | 
			
		||||
| 11  | WIFI_CONNECT                            |                            | MUST     |
 | 
			
		||||
| 12  | WIFI_CONNECT_NONBLOCK                   |                            | SHOULD   |
 | 
			
		||||
| 12  | WIFI_CONNECT_DISCONNECT_NONBLOCK        |                            | SHOULD   |
 | 
			
		||||
| 13  | WIFI_CONNECT_SECURE                     | With security type:        |          |
 | 
			
		||||
|     |                                         | NSAPI_SECURITY_WEP         | SHOULD   |
 | 
			
		||||
|     |                                         | NSAPI_SECURITY_WPA         | SHOULD   |
 | 
			
		||||
| 
						 | 
				
			
			@ -385,7 +385,7 @@ Test `WiFiInterface::connect()` without parameters. Use `set_credentials()` for
 | 
			
		|||
 | 
			
		||||
`connect()` calls return `NSAPI_ERROR_OK`.
 | 
			
		||||
 | 
			
		||||
### WIFI_CONNECT_NONBLOCK
 | 
			
		||||
### WIFI_CONNECT_DISCONNECT_NONBLOCK
 | 
			
		||||
 | 
			
		||||
**Description:**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -399,18 +399,24 @@ Test `WiFiInterface::connect()` and `WiFiInterface::disconnect()` in non-blockin
 | 
			
		|||
 | 
			
		||||
1.  Initialize the driver.
 | 
			
		||||
2.  `Call WiFiInterface::set_credentials( <ssid:unsecure>, NULL)`.
 | 
			
		||||
3.  `Call WiFiInterface::connect()`.
 | 
			
		||||
4.  `Call WiFiInterface::set_blocking(false)`
 | 
			
		||||
5.  `Call WiFiInterface::get_connection_status()`
 | 
			
		||||
6.  `disconnect()`
 | 
			
		||||
7.  `Call WiFiInterface::get_connection_status()`
 | 
			
		||||
8.  `Call WiFiInterface::set_blocking(true)`
 | 
			
		||||
3.  `Call WiFiInterface::set_blocking(false)`
 | 
			
		||||
4.  `Call WiFiInterface::connect()`.
 | 
			
		||||
5.  `Cal WiFiInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)`
 | 
			
		||||
6.  `Call WiFiInterface::connect()`.
 | 
			
		||||
7.  `disconnect()`
 | 
			
		||||
8.  `disconnect()`
 | 
			
		||||
9. `Call WiFiInterface::set_blocking(true)`
 | 
			
		||||
 | 
			
		||||
**Expected result:**
 | 
			
		||||
 | 
			
		||||
 In case of drivers which do not support asynchronous mode `set_blocking(false)` call returns `NSAPI_ERROR_UNSUPPORTED` and skips test case, otherwise:
 | 
			
		||||
`connect()` call returns  `NSAPI_ERROR_OK`. To confirm connection `get_connection_status()` calls return `NSAPI_STATUS_GLOBAL_UP` or `NSAPI_STATUS_LOCAL_UP`.
 | 
			
		||||
`disconnect()` call returns `NSAPI_ERROR_OK`. To confirm disconnection `get_connection_status()` calls return `NSAPI_STATUS_DISCONNECTED`.
 | 
			
		||||
1. Drivers which do not support asynchronous mode `set_blocking(false)` call returns `NSAPI_ERROR_UNSUPPORTED` and skips test case.
 | 
			
		||||
2. `connect()` call returns  `NSAPI_ERROR_OK`. 
 | 
			
		||||
3. `set_credentials(...)` call returns `NSAPI_ERROR_BUSY`. 
 | 
			
		||||
4. Second `connect()` call returns `NSAPI_ERROR_BUSY` or `NSAPI_ERROR_IS_CONNECTED`.
 | 
			
		||||
5. Attached callback informs about connection status. Callback reports status `NSAPI_STATUS_CONNECTING` and `NSAPI_STATUS_CONNECTED`. 
 | 
			
		||||
6. `disconnect()` call returns `NSAPI_ERROR_OK`. 
 | 
			
		||||
7. Second `disconnect()` call returns `NSAPI_ERROR_BUSY` or `NSAPI_ERROR_IS_CONNECTED`. 
 | 
			
		||||
8. To confirm disconnection callback reports `NSAPI_STATUS_DISCONNECTED`.
 | 
			
		||||
 | 
			
		||||
### WIFI_CONNECT_SECURE
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ Case cases[] = {
 | 
			
		|||
    Case("WIFI-CONNECT-PARAMS-VALID-UNSECURE", wifi_connect_params_valid_unsecure),
 | 
			
		||||
    Case("WIFI-CONNECT", wifi_connect),
 | 
			
		||||
    //Most boards are not passing this test, but they should if they support non-blocking API.
 | 
			
		||||
    //Case("WIFI-CONNECT-NONBLOCKING", wifi_connect_nonblock),
 | 
			
		||||
    //Case("WIFI_CONNECT_DISCONNECT_NONBLOCK", wifi_connect_disconnect_nonblock),
 | 
			
		||||
    Case("WIFI-CONNECT-DISCONNECT-REPEAT", wifi_connect_disconnect_repeat),
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBED_CONF_APP_WIFI_SECURE_SSID)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ using namespace utest::v1;
 | 
			
		|||
nsapi_connection_status_t status_connection;
 | 
			
		||||
Semaphore sem_conn(0, 1);
 | 
			
		||||
Semaphore sem_disconn(0, 1);
 | 
			
		||||
Semaphore sem_connecting(0, 1);
 | 
			
		||||
void status_callback(nsapi_event_t e, intptr_t d)
 | 
			
		||||
{
 | 
			
		||||
    if (d == NSAPI_STATUS_LOCAL_UP || d == NSAPI_STATUS_GLOBAL_UP) {
 | 
			
		||||
| 
						 | 
				
			
			@ -40,9 +41,14 @@ void status_callback(nsapi_event_t e, intptr_t d)
 | 
			
		|||
        status_connection = (nsapi_connection_status_t)d;
 | 
			
		||||
        sem_disconn.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (d == NSAPI_STATUS_CONNECTING) {
 | 
			
		||||
        status_connection = (nsapi_connection_status_t)d;
 | 
			
		||||
        sem_connecting.release();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wifi_connect_nonblock(void)
 | 
			
		||||
void wifi_connect_disconnect_nonblock(void)
 | 
			
		||||
{
 | 
			
		||||
    WiFiInterface *wifi = get_interface();
 | 
			
		||||
    char ssid[SSID_MAX_LEN + 1] = MBED_CONF_APP_WIFI_UNSECURE_SSID;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,16 +56,25 @@ void wifi_connect_nonblock(void)
 | 
			
		|||
    wifi->attach(status_callback);
 | 
			
		||||
    TEST_SKIP_UNLESS(wifi->set_blocking(false) != NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
    nsapi_error_t ret = wifi->connect();
 | 
			
		||||
    nsapi_error_t ret2 = wifi->set_credentials("1234", "1234", NSAPI_SECURITY_WPA_WPA2);
 | 
			
		||||
    nsapi_error_t ret3 = wifi->connect();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, ret);
 | 
			
		||||
    bool res = sem_conn.try_acquire_for(30000);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_BUSY, ret2);
 | 
			
		||||
    TEST_ASSERT_TRUE(ret3 == NSAPI_ERROR_BUSY || ret3 == NSAPI_ERROR_IS_CONNECTED);
 | 
			
		||||
    bool res = sem_connecting.try_acquire_for(30000);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(NSAPI_STATUS_CONNECTING, status_connection);
 | 
			
		||||
    res = sem_conn.try_acquire_for(30000);
 | 
			
		||||
    TEST_ASSERT_TRUE(res == true);
 | 
			
		||||
    TEST_ASSERT_TRUE(status_connection == NSAPI_STATUS_GLOBAL_UP || status_connection == NSAPI_STATUS_LOCAL_UP);
 | 
			
		||||
    ret = wifi->disconnect();
 | 
			
		||||
    ret3 = wifi->disconnect();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, ret);
 | 
			
		||||
    TEST_ASSERT_TRUE(ret3 == NSAPI_ERROR_BUSY || ret3 == NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
    res = sem_disconn.try_acquire_for(30000);
 | 
			
		||||
    TEST_ASSERT_TRUE(res == true);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(NSAPI_STATUS_DISCONNECTED, status_connection);
 | 
			
		||||
    wifi->set_blocking(true);
 | 
			
		||||
    wifi->attach(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // defined(MBED_CONF_APP_WIFI_UNSECURE_SSID)
 | 
			
		||||
| 
						 | 
				
			
			@ -63,8 +63,8 @@ void wifi_connect_params_channel_fail(void);
 | 
			
		|||
/** Test WiFiInterface::connect() without parameters. Use set_credentials() for setting parameters. */
 | 
			
		||||
void wifi_connect(void);
 | 
			
		||||
 | 
			
		||||
/** Test WiFiInterface::connect() in nonblocking mode. Use set_credentials() for setting parameters. */
 | 
			
		||||
void wifi_connect_nonblock(void);
 | 
			
		||||
/** Test WiFiInterface::connect() and disconnect() in nonblocking mode. Use set_credentials() for setting parameters. */
 | 
			
		||||
void wifi_connect_disconnect_nonblock(void);
 | 
			
		||||
 | 
			
		||||
/** Test WiFiInterface::connect() without parameters. Don't set parameters with set_credentials() */
 | 
			
		||||
void wifi_connect_nocredentials(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,7 +69,8 @@ ESP8266Interface::ESP8266Interface()
 | 
			
		|||
      _conn_stat_cb(NULL),
 | 
			
		||||
      _global_event_queue(mbed_event_queue()), // Needs to be set before attaching event() to SIGIO
 | 
			
		||||
      _oob_event_id(0),
 | 
			
		||||
      _connect_event_id(0)
 | 
			
		||||
      _connect_event_id(0),
 | 
			
		||||
      _software_conn_stat(IFACE_STATUS_DISCONNECTED)
 | 
			
		||||
{
 | 
			
		||||
    memset(_cbs, 0, sizeof(_cbs));
 | 
			
		||||
    memset(ap_ssid, 0, sizeof(ap_ssid));
 | 
			
		||||
| 
						 | 
				
			
			@ -192,6 +193,12 @@ void ESP8266Interface::PowerPin::power_off()
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESP8266Interface::_power_off()
 | 
			
		||||
{
 | 
			
		||||
    _rst_pin.rst_assert();
 | 
			
		||||
    _pwr_pin.power_off();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ESP8266Interface::PowerPin::is_connected()
 | 
			
		||||
{
 | 
			
		||||
    return _pwr_pin.is_connected();
 | 
			
		||||
| 
						 | 
				
			
			@ -214,6 +221,20 @@ int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security
 | 
			
		|||
 | 
			
		||||
void ESP8266Interface::_connect_async()
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t status = _init();
 | 
			
		||||
    if (status != NSAPI_ERROR_OK) {
 | 
			
		||||
        _connect_retval = status;
 | 
			
		||||
        _software_conn_stat = IFACE_STATUS_DISCONNECTED;
 | 
			
		||||
        //_conn_stat_cb will be called from refresh_conn_state_cb
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_esp.dhcp(true, 1)) {
 | 
			
		||||
        _connect_retval = NSAPI_ERROR_DHCP_FAILURE;
 | 
			
		||||
        _software_conn_stat = IFACE_STATUS_DISCONNECTED;
 | 
			
		||||
        //_conn_stat_cb will be called from refresh_conn_state_cb
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    _cmutex.lock();
 | 
			
		||||
    if (!_connect_event_id) {
 | 
			
		||||
        tr_debug("_connect_async(): cancelled");
 | 
			
		||||
| 
						 | 
				
			
			@ -222,14 +243,18 @@ void ESP8266Interface::_connect_async()
 | 
			
		|||
    }
 | 
			
		||||
    _connect_retval = _esp.connect(ap_ssid, ap_pass);
 | 
			
		||||
    int timeleft_ms = ESP8266_INTERFACE_CONNECT_TIMEOUT_MS - _conn_timer.read_ms();
 | 
			
		||||
    if (_connect_retval == NSAPI_ERROR_OK || _connect_retval == NSAPI_ERROR_AUTH_FAILURE
 | 
			
		||||
    if (_connect_retval == NSAPI_ERROR_OK
 | 
			
		||||
            || _connect_retval == NSAPI_ERROR_AUTH_FAILURE
 | 
			
		||||
            || _connect_retval == NSAPI_ERROR_NO_SSID
 | 
			
		||||
            || ((_if_blocking == true) && (timeleft_ms <= 0))) {
 | 
			
		||||
        _connect_event_id = 0;
 | 
			
		||||
        _conn_timer.stop();
 | 
			
		||||
        if (timeleft_ms <= 0) {
 | 
			
		||||
        if (timeleft_ms <= 0 && _connect_retval != NSAPI_ERROR_OK) {
 | 
			
		||||
            _connect_retval = NSAPI_ERROR_CONNECTION_TIMEOUT;
 | 
			
		||||
        }
 | 
			
		||||
        if (_connect_retval != NSAPI_ERROR_OK) {
 | 
			
		||||
            _software_conn_stat = IFACE_STATUS_DISCONNECTED;
 | 
			
		||||
        }
 | 
			
		||||
        _if_connected.notify_all();
 | 
			
		||||
    } else {
 | 
			
		||||
        // Postpone to give other stuff time to run
 | 
			
		||||
| 
						 | 
				
			
			@ -241,13 +266,24 @@ void ESP8266Interface::_connect_async()
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    _cmutex.unlock();
 | 
			
		||||
 | 
			
		||||
    if (_connect_event_id == 0) {
 | 
			
		||||
        if (_conn_stat_cb) {
 | 
			
		||||
            _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
 | 
			
		||||
        }
 | 
			
		||||
        if (_conn_stat == NSAPI_STATUS_GLOBAL_UP || _conn_stat == NSAPI_STATUS_LOCAL_UP) {
 | 
			
		||||
            _software_conn_stat = IFACE_STATUS_CONNECTED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ESP8266Interface::connect()
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t status = _conn_status_to_error();
 | 
			
		||||
    if (status != NSAPI_ERROR_NO_CONNECTION) {
 | 
			
		||||
        return status;
 | 
			
		||||
    if (_software_conn_stat == IFACE_STATUS_CONNECTING) {
 | 
			
		||||
        return NSAPI_ERROR_BUSY;
 | 
			
		||||
    }
 | 
			
		||||
    if (_software_conn_stat == IFACE_STATUS_CONNECTED) {
 | 
			
		||||
        return NSAPI_ERROR_IS_CONNECTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (strlen(ap_ssid) == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,22 +295,15 @@ int ESP8266Interface::connect()
 | 
			
		|||
            return NSAPI_ERROR_PARAMETER;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = _init();
 | 
			
		||||
    if (status != NSAPI_ERROR_OK) {
 | 
			
		||||
        return status;
 | 
			
		||||
    if (!_if_blocking) {
 | 
			
		||||
        bool ret = _cmutex.trylock();
 | 
			
		||||
        if (ret == false) {
 | 
			
		||||
            return NSAPI_ERROR_BUSY;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        _cmutex.lock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (get_ip_address()) {
 | 
			
		||||
        return NSAPI_ERROR_IS_CONNECTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_esp.dhcp(true, 1)) {
 | 
			
		||||
        return NSAPI_ERROR_DHCP_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _cmutex.lock();
 | 
			
		||||
 | 
			
		||||
    _software_conn_stat = IFACE_STATUS_CONNECTING;
 | 
			
		||||
    _connect_retval = NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
    MBED_ASSERT(!_connect_event_id);
 | 
			
		||||
    _conn_timer.stop();
 | 
			
		||||
| 
						 | 
				
			
			@ -304,6 +333,9 @@ int ESP8266Interface::connect()
 | 
			
		|||
int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t status = _conn_status_to_error();
 | 
			
		||||
    if (_software_conn_stat == IFACE_STATUS_CONNECTING) {
 | 
			
		||||
        return NSAPI_ERROR_BUSY;
 | 
			
		||||
    }
 | 
			
		||||
    if (status != NSAPI_ERROR_NO_CONNECTION) {
 | 
			
		||||
        return status;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -351,41 +383,100 @@ int ESP8266Interface::set_channel(uint8_t channel)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int ESP8266Interface::disconnect()
 | 
			
		||||
void ESP8266Interface::_disconnect_async()
 | 
			
		||||
{
 | 
			
		||||
    _cmutex.lock();
 | 
			
		||||
    _disconnect_retval = _esp.disconnect() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
    int timeleft_ms = ESP8266_INTERFACE_CONNECT_TIMEOUT_MS - _conn_timer.read_ms();
 | 
			
		||||
 | 
			
		||||
    if (_disconnect_retval == NSAPI_ERROR_OK || ((_if_blocking == true) && (timeleft_ms <= 0))) {
 | 
			
		||||
 | 
			
		||||
        if (timeleft_ms <= 0 && _connect_retval != NSAPI_ERROR_OK) {
 | 
			
		||||
            _disconnect_retval = NSAPI_ERROR_CONNECTION_TIMEOUT;
 | 
			
		||||
        } else {
 | 
			
		||||
            if (_conn_stat != NSAPI_STATUS_DISCONNECTED) {
 | 
			
		||||
                _conn_stat = NSAPI_STATUS_DISCONNECTED;
 | 
			
		||||
            }
 | 
			
		||||
            // In case the status update arrives later inform upper layers manually
 | 
			
		||||
            _disconnect_event_id = 0;
 | 
			
		||||
            _conn_timer.stop();
 | 
			
		||||
            _connect_retval = NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _power_off();
 | 
			
		||||
        _if_connected.notify_all();
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        // Postpone to give other stuff time to run
 | 
			
		||||
        _disconnect_event_id = _global_event_queue->call_in(
 | 
			
		||||
                                   ESP8266_INTERFACE_CONNECT_INTERVAL_MS,
 | 
			
		||||
                                   callback(this, &ESP8266Interface::_disconnect_async));
 | 
			
		||||
        if (!_disconnect_event_id) {
 | 
			
		||||
            MBED_ERROR(
 | 
			
		||||
                MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
 | 
			
		||||
                "ESP8266Interface::_disconnect_async(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    _cmutex.unlock();
 | 
			
		||||
    _software_conn_stat = IFACE_STATUS_DISCONNECTED;
 | 
			
		||||
 | 
			
		||||
    if (_disconnect_event_id == 0) {
 | 
			
		||||
        if (_conn_stat_cb) {
 | 
			
		||||
            _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ESP8266Interface::disconnect()
 | 
			
		||||
{
 | 
			
		||||
    if (_software_conn_stat == IFACE_STATUS_DISCONNECTING) {
 | 
			
		||||
        return NSAPI_ERROR_BUSY;
 | 
			
		||||
    }
 | 
			
		||||
    if (_software_conn_stat == IFACE_STATUS_DISCONNECTED) {
 | 
			
		||||
        return NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
    if (!_if_blocking) {
 | 
			
		||||
        bool ret = _cmutex.trylock();
 | 
			
		||||
        if (ret == false) {
 | 
			
		||||
            return NSAPI_ERROR_BUSY;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        _cmutex.lock();
 | 
			
		||||
    }
 | 
			
		||||
    if (_connect_event_id) {
 | 
			
		||||
        _global_event_queue->cancel(_connect_event_id);
 | 
			
		||||
        _connect_event_id = 0; // cancel asynchronous connection attempt if one is ongoing
 | 
			
		||||
    }
 | 
			
		||||
    _cmutex.unlock();
 | 
			
		||||
    _software_conn_stat = IFACE_STATUS_DISCONNECTING;
 | 
			
		||||
 | 
			
		||||
    _disconnect_retval = NSAPI_ERROR_IS_CONNECTED;
 | 
			
		||||
    _disconnect_event_id = 0;
 | 
			
		||||
 | 
			
		||||
    _initialized = false;
 | 
			
		||||
    _conn_timer.stop();
 | 
			
		||||
    _conn_timer.reset();
 | 
			
		||||
    _conn_timer.start();
 | 
			
		||||
 | 
			
		||||
    nsapi_error_t status = _conn_status_to_error();
 | 
			
		||||
    if (status == NSAPI_ERROR_NO_CONNECTION) {
 | 
			
		||||
        return NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
    _disconnect_event_id = _global_event_queue->call(
 | 
			
		||||
                               callback(this, &ESP8266Interface::_disconnect_async));
 | 
			
		||||
 | 
			
		||||
    if (!_disconnect_event_id) {
 | 
			
		||||
        MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM),
 | 
			
		||||
                   "disconnect(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int ret = _esp.disconnect() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
 | 
			
		||||
    if (ret == NSAPI_ERROR_OK) {
 | 
			
		||||
        // Try to lure the nw status update from ESP8266, might come later
 | 
			
		||||
        _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
 | 
			
		||||
        // In case the status update arrives later inform upper layers manually
 | 
			
		||||
        if (_conn_stat != NSAPI_STATUS_DISCONNECTED) {
 | 
			
		||||
            _conn_stat = NSAPI_STATUS_DISCONNECTED;
 | 
			
		||||
            if (_conn_stat_cb) {
 | 
			
		||||
                _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    while (_if_blocking
 | 
			
		||||
            && (_conn_status_to_error() != NSAPI_ERROR_NO_CONNECTION)
 | 
			
		||||
            && (_disconnect_retval != NSAPI_ERROR_OK)) {
 | 
			
		||||
        _if_connected.wait();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Power down the modem
 | 
			
		||||
    _rst_pin.rst_assert();
 | 
			
		||||
    // Power off the modem
 | 
			
		||||
    _pwr_pin.power_off();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
    _cmutex.unlock();
 | 
			
		||||
    if (!_if_blocking) {
 | 
			
		||||
        return NSAPI_ERROR_OK;
 | 
			
		||||
    } else {
 | 
			
		||||
        return _disconnect_retval;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *ESP8266Interface::get_ip_address()
 | 
			
		||||
| 
						 | 
				
			
			@ -866,9 +957,15 @@ void ESP8266Interface::refresh_conn_state_cb()
 | 
			
		|||
        // Doesn't require changes
 | 
			
		||||
        case NSAPI_STATUS_CONNECTING:
 | 
			
		||||
        case NSAPI_STATUS_GLOBAL_UP:
 | 
			
		||||
            if (_software_conn_stat == IFACE_STATUS_DISCONNECTED) {
 | 
			
		||||
                _software_conn_stat = IFACE_STATUS_CONNECTED;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        // Start from scratch if connection drops/is dropped
 | 
			
		||||
        case NSAPI_STATUS_DISCONNECTED:
 | 
			
		||||
            if (_software_conn_stat == IFACE_STATUS_CONNECTED) {
 | 
			
		||||
                _software_conn_stat = IFACE_STATUS_DISCONNECTED;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        // Handled on AT layer
 | 
			
		||||
        case NSAPI_STATUS_LOCAL_UP:
 | 
			
		||||
| 
						 | 
				
			
			@ -888,8 +985,14 @@ void ESP8266Interface::refresh_conn_state_cb()
 | 
			
		|||
 | 
			
		||||
    tr_debug("refresh_conn_state_cb(): changed to %d", _conn_stat);
 | 
			
		||||
 | 
			
		||||
    // Inform upper layers
 | 
			
		||||
    if (_conn_stat_cb) {
 | 
			
		||||
        // _conn_stat_cb will be called in _connect_async or disconnect_assync to avoid race condition
 | 
			
		||||
        if ((_software_conn_stat == IFACE_STATUS_CONNECTING
 | 
			
		||||
                || _software_conn_stat == IFACE_STATUS_DISCONNECTING)
 | 
			
		||||
                && (_conn_stat != NSAPI_STATUS_CONNECTING)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -904,8 +1007,6 @@ nsapi_error_t ESP8266Interface::_conn_status_to_error()
 | 
			
		|||
{
 | 
			
		||||
    nsapi_error_t ret;
 | 
			
		||||
 | 
			
		||||
    _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
 | 
			
		||||
 | 
			
		||||
    switch (_conn_stat) {
 | 
			
		||||
        case NSAPI_STATUS_DISCONNECTED:
 | 
			
		||||
            ret = NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -381,6 +381,15 @@ private:
 | 
			
		|||
    ESP8266 _esp;
 | 
			
		||||
    void refresh_conn_state_cb();
 | 
			
		||||
 | 
			
		||||
    /** Status of software connection
 | 
			
		||||
     */
 | 
			
		||||
    typedef enum esp_connection_software_status {
 | 
			
		||||
        IFACE_STATUS_DISCONNECTED = 0,
 | 
			
		||||
        IFACE_STATUS_CONNECTING = 1,
 | 
			
		||||
        IFACE_STATUS_CONNECTED = 2,
 | 
			
		||||
        IFACE_STATUS_DISCONNECTING = 3
 | 
			
		||||
    } esp_connection_software_status_t;
 | 
			
		||||
 | 
			
		||||
    // HW reset pin
 | 
			
		||||
    class ResetPin {
 | 
			
		||||
    public:
 | 
			
		||||
| 
						 | 
				
			
			@ -403,6 +412,12 @@ private:
 | 
			
		|||
        mbed::DigitalOut  _pwr_pin;
 | 
			
		||||
    } _pwr_pin;
 | 
			
		||||
 | 
			
		||||
    /** Assert the reset and power pins
 | 
			
		||||
     *  ESP8266 has two pins serving similar purpose and this function asserts them both
 | 
			
		||||
     *  if they are configured in mbed_app.json.
 | 
			
		||||
     */
 | 
			
		||||
    void _power_off();
 | 
			
		||||
 | 
			
		||||
    // Credentials
 | 
			
		||||
    static const int ESP8266_SSID_MAX_LENGTH = 32; /* 32 is what 802.11 defines as longest possible name */
 | 
			
		||||
    char ap_ssid[ESP8266_SSID_MAX_LENGTH + 1]; /* The longest possible name; +1 for the \0 */
 | 
			
		||||
| 
						 | 
				
			
			@ -437,6 +452,7 @@ private:
 | 
			
		|||
    // Driver's state
 | 
			
		||||
    int _initialized;
 | 
			
		||||
    nsapi_error_t _connect_retval;
 | 
			
		||||
    nsapi_error_t _disconnect_retval;
 | 
			
		||||
    bool _get_firmware_ok();
 | 
			
		||||
    nsapi_error_t _init(void);
 | 
			
		||||
    nsapi_error_t _reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -459,9 +475,12 @@ private:
 | 
			
		|||
    events::EventQueue *_global_event_queue;
 | 
			
		||||
    int _oob_event_id;
 | 
			
		||||
    int _connect_event_id;
 | 
			
		||||
    int _disconnect_event_id;
 | 
			
		||||
    void proc_oob_evnt();
 | 
			
		||||
    void _connect_async();
 | 
			
		||||
    void _disconnect_async();
 | 
			
		||||
    rtos::Mutex _cmutex; // Protect asynchronous connection logic
 | 
			
		||||
    esp_connection_software_status_t _software_conn_stat ;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue