diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp index 2e33400769..5c2e911afb 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp @@ -1201,4 +1201,29 @@ nsapi_connection_status_t ESP8266::connection_status() const { return _conn_status; } + +bool ESP8266::set_country_code_policy(bool track_ap, const char *country_code, int channel_start, int channels) +{ + int t_ap = track_ap ? 0 : 1; + + _smutex.lock(); + bool done = _parser.send("AT+CWCOUNTRY_DEF=%d,\"%s\",%d,%d", t_ap, country_code, channel_start, channels) + && _parser.recv("OK\n"); + + if (!done) { + tr_error("\"AT+CWCOUNTRY_DEF=%d,\"%s\",%d,%d\" - FAIL", t_ap, country_code, channel_start, channels); + } + + done &= _parser.send("AT+CWCOUNTRY_CUR=%d,\"%s\",%d,%d", t_ap, country_code, channel_start, channels) + && _parser.recv("OK\n"); + + if (!done) { + tr_error("\"AT+CWCOUNTRY_CUR=%d,\"%s\",%d,%d\" - FAIL", t_ap, country_code, channel_start, channels); + } + + _smutex.unlock(); + + return done; +} + #endif diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.h b/components/wifi/esp8266-driver/ESP8266/ESP8266.h index 68688243bf..542d7c100a 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.h +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.h @@ -335,6 +335,15 @@ public: */ bool set_default_wifi_mode(const int8_t mode); + /** + * @param track_ap if TRUE, sets the county code to be the same as the AP's that ESP is connected to, + * if FALSE the code will not change + * @param country_code ISO 3166-1 Alpha-2 coded country code + * @param channel_start the channel number to start at + * @param channels number of channels + */ + bool set_country_code_policy(bool track_ap, const char *country_code, int channel_start, int channels); + /** Get the connection status * * @return The connection status according to ConnectionStatusType diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index 296804cda0..be6ae90af7 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -69,6 +69,11 @@ ESP8266Interface::ESP8266Interface() memset(ap_ssid, 0, sizeof(ap_ssid)); memset(ap_pass, 0, sizeof(ap_pass)); + _ch_info.track_ap = true; + strncpy(_ch_info.country_code, MBED_CONF_ESP8266_COUNTRY_CODE, sizeof(_ch_info.country_code)); + _ch_info.channel_start = MBED_CONF_ESP8266_CHANNEL_START; + _ch_info.channels = MBED_CONF_ESP8266_CHANNELS; + _esp.sigio(this, &ESP8266Interface::event); _esp.set_timeout(); _esp.attach(this, &ESP8266Interface::refresh_conn_state_cb); @@ -98,6 +103,11 @@ ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName r memset(ap_ssid, 0, sizeof(ap_ssid)); memset(ap_pass, 0, sizeof(ap_pass)); + _ch_info.track_ap = true; + strncpy(_ch_info.country_code, MBED_CONF_ESP8266_COUNTRY_CODE, sizeof(_ch_info.country_code)); + _ch_info.channel_start = MBED_CONF_ESP8266_CHANNEL_START; + _ch_info.channels = MBED_CONF_ESP8266_CHANNELS; + _esp.sigio(this, &ESP8266Interface::event); _esp.set_timeout(); _esp.attach(this, &ESP8266Interface::refresh_conn_state_cb); @@ -407,6 +417,9 @@ nsapi_error_t ESP8266Interface::_init(void) if (!_esp.set_default_wifi_mode(ESP8266::WIFIMODE_STATION)) { return NSAPI_ERROR_DEVICE_ERROR; } + if (!_esp.set_country_code_policy(true, _ch_info.country_code, _ch_info.channel_start, _ch_info.channels)) { + return NSAPI_ERROR_DEVICE_ERROR; + } if (!_esp.cond_enable_tcp_passive_mode()) { return NSAPI_ERROR_DEVICE_ERROR; } @@ -855,5 +868,26 @@ nsapi_error_t ESP8266Interface::set_blocking(bool blocking) return NSAPI_ERROR_OK; } +nsapi_error_t ESP8266Interface::set_country_code(bool track_ap, const char *country_code, int len, int channel_start, int channels) +{ + for (int i = 0; i < len; i++) { + // Validation done by firmware + if (!country_code[i]) { + tr_warning("invalid country code"); + return NSAPI_ERROR_PARAMETER; + } + } + + _ch_info.track_ap = track_ap; + + // Firmware takes only first three characters + strncpy(_ch_info.country_code, country_code, sizeof(_ch_info.country_code)); + _ch_info.country_code[sizeof(_ch_info.country_code)-1] = '\0'; + + _ch_info.channel_start = channel_start; + _ch_info.channels = channels; + + return NSAPI_ERROR_OK; +} #endif diff --git a/components/wifi/esp8266-driver/ESP8266Interface.h b/components/wifi/esp8266-driver/ESP8266Interface.h index e811ec3c6c..bb2d888752 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.h +++ b/components/wifi/esp8266-driver/ESP8266Interface.h @@ -44,6 +44,18 @@ #endif #endif /* TARGET_FF_ARDUINO */ +#ifndef MBED_CONF_ESP8266_COUNTRY_CODE +#define MBED_CONF_ESP8266_COUNTRY_CODE "CN" +#endif + +#ifndef MBED_CONF_ESP8266_CHANNEL_START +#define MBED_CONF_ESP8266_CHANNEL_START 1 +#endif + +#ifndef MBED_CONF_ESP8266_CHANNELS +#define MBED_CONF_ESP8266_CHANNELS 13 +#endif + /** ESP8266Interface class * Implementation of the NetworkStack for the ESP8266 */ @@ -325,6 +337,18 @@ protected: */ virtual nsapi_error_t set_blocking(bool blocking); + /** Set country code + * + * @param track_ap if TRUE, use country code used by the AP ESP is connected to, + * otherwise uses country_code always + * @param country_code ISO 3166-1 coded, 2 character alphanumeric country code assumed + * @param len Length of the country code + * @param channel_start The channel number to start at + * @param channel Number of channels + * @return NSAPI_ERROR_OK on success, negative error code on failure. + */ + nsapi_error_t set_country_code(bool track_ap, const char *country_code, int len, int channel_start, int channels); + private: // AT layer ESP8266 _esp; @@ -350,6 +374,15 @@ private: char ap_pass[ESP8266_PASSPHRASE_MAX_LENGTH + 1]; /* The longest possible passphrase; +1 for the \0 */ nsapi_security_t _ap_sec; + // Country code + struct _channel_info { + bool track_ap; // Set country code based on the AP ESP is connected to + char country_code[4]; // ISO 3166-1 coded, 2-3 character alphanumeric country code - +1 for the '\0' - assumed. Documentation doesn't tell. + int channel_start; + int channels; + }; + struct _channel_info _ch_info; + bool _if_blocking; // NetworkInterface, blocking or not rtos::ConditionVariable _if_connected; diff --git a/components/wifi/esp8266-driver/mbed_lib.json b/components/wifi/esp8266-driver/mbed_lib.json index 28337d8077..eeab548a1c 100644 --- a/components/wifi/esp8266-driver/mbed_lib.json +++ b/components/wifi/esp8266-driver/mbed_lib.json @@ -32,6 +32,18 @@ "socket-bufsize": { "help": "Max socket data heap usage", "value": 8192 + }, + "country-code": { + "help": "ISO 3166-1 coded, 2 character alphanumeric country code, 'CN' by default", + "value": null + }, + "channel-start": { + "help": "the channel number to start at, 1 by default", + "value": null + }, + "channels": { + "help": "channel count, 13 by default", + "value": null } }, "target_overrides": {